Advanced Component styling with Angular (v4+)
slides.com/gerardsans | @gerardsans
Text
Google Developer Expert
Master of Ceremonies
Blogger
International Speaker
Angular Trainer (v4+)
Community Leader
850
950
Angular In Flip Flops
Music Player Component
Layout
hover
Title/Artist
Selected
Song Track Component
@Component({
selector: 'song-track', // <song-track></song-track>
template: `
<div class="container">
<track-image image="http://..."></track-image>
<div class="track-information">
<track-title>{{track}}</track-title>
<track-artist>{{artist}}</track-artist>
</div>
</div>`
})
export class SongTrack { }
Component Styles
Inline Styles
@Component({
selector: 'song-track',
styles: [`.container { color: white; }`]
})
export class SongTrack { }
Template Inline Styles
@Component({
template: `
<style>
.container { color: deepskyblue; }
</style>
<div class="container">...</div>
`
})
export class SongTrack { }
External Styles
//song-track.component.ts
@Component({
styleUrls: ['src/shared.css'],
})
export class SongTrack { }
//shared.css
.container { ... }
Styling
Directives
Selecting a Track
ngClass (single)
<song-track ngClass="selected" class="large"></song-track>
<song-track [ngClass]="'selected'"></song-track>
<song-track [ngClass]="['selected']"></song-track>
<song-track [ngClass]="{'selected': true}"></song-track>
<song-track class="selected large"></song-track>
<song-track class="selected"></song-track>
ngClass (multiple)
<song-track ngClass="selected large">
<song-track [ngClass]="'selected large'">
<song-track [ngClass]="['selected', 'large']">
<song-track [ngClass]="{'selected': true, 'large': true}">
<song-track [ngClass]="{'selected large': true}">
<song-track class="selected large"></song-track>
Styling
Song Title
ngStyle (single)
<song-track [ngStyle]="{'color': 'white'}" style="font-size: 12px;">
<song-track [ngStyle]="{'font-size.px': '12'}">
<song-track [ngStyle]="{'font-size': '12px'}">
<song-track style="color: white; font-size: 12px;">
<song-track style="font-size: 12px;">
ngStyle (multiple)
<song-track [ngStyle]="{'color': 'white', 'font-size': '12px'}">
<song-track style="color: white; font-size: 12px;">
Using host metadata
@Component.host (styling)
@Component({
host: {
//setting multiple values
'class': 'selected disabled',
'style': 'color: purple; margin: 5px;',
//setting single values (using binding)
'[class.selected]': 'true',
'[class.selected]': '!!selected', //add class if selected = true
'[style.color]': '"purple"' //expression must be a string
}
})
export class SongTrack { }
@HostBinding (styling)
@Component({
})
export class SongTrack {
//<host class="selected"></host>
@HostBinding('class.selected') selected = true;
//<host style="color: red;"></host>
@HostBinding('style.color') color = 'red';
}
Shadow DOM
Shadow DOM
- Isolated DOM
- Scoped CSS
- Composition
- Productivity
Browser Support
safari
safari
Styles Encapsulation
Emulated
Shadow DOM
Emulated Shadow DOM
@Component({
selector: 'song-track',
encapsulation: ViewEncapsulation.Emulated
})
<head>
<style>
.container[_ngcontent-ikt-1] { ... }
</style>
</head>
<body>
<my-app>
<song-track _nghost-ikt-1>
<div _ngcontent-ikt-1 class="container"></div>
</song-track>
</my-app>
</body>
Native Shadow DOM
Native Shadow DOM
@Component({
selector: 'song-track',
encapsulation: ViewEncapsulation.Native
})
<body>
<my-app>
<song-track>
▾ #shadow-root (open)
<style>.container { ... }</style>
<div class="container"></div>
</song-track>
</my-app>
</body>
Disabled Shadow DOM
Disabled Shadow DOM
@Component({
selector: 'song-track',
encapsulation: ViewEncapsulation.None
})
<head>
<style>.container { ... }</style>
</head>
<body>
<my-app>
<song-track>
<div class="container"></div>
</song-track>
</my-app>
</body>
Styling
Shadow DOM
Container Styling (:host)
@Component({
styles: [`
:host { color: black; }
:host(.selected) { color: red; }
`]
})
export class SongTrack { }
<song-track></song-track>
<song-track class="selected"></song-track>
Context Styling (:host-context)
:host-context(.theme) { color: red; }
:host-context(#player1) { color: red; }
<div class="theme">
<song-track></song-track>
</div>
<div id="player1">
<song-track></song-track>
</div>
Overriding Styles (/deep/)
@Component({
styles: [`
:host /deep/ .h3 { color: red; }
:host >>> .h4 { color: purple; }
`],
template: `
<div class="container">
<track-image image="http://..."></track-image>
<div class="track-information">
<track-title>{{track}}</track-title> //<h3><ng-content></h3>
<track-artist>{{artist}}</track-artist> //<h4><ng-content></h4>
</div>
</div>`
})
export class SongTrack { }
Angular
Platforms
ElementRef (only browser)
import { ElementRef } from '@angular/core';
@Component(...)
export class SongTrack {
constructor(private element: ElementRef){
let elem = this.element.nativeElement;
elem.style.color = "blue";
elem.style.cssText = "color: blue; ..."; // multiple styles
elem.setAttribute("style", "color: blue;");
}
}
Renderer2 (all platforms)
import { ElementRef, Renderer2 } from '@angular/core';
@Component(...)
export class SongTrack {
constructor(
private element: ElementRef,
private renderer: Renderer2
){
let elem = this.element.nativeElement;
renderer.setStyle(elem, "color", "blue");
renderer.addClass(elem, "selected", true);
}
}
Playground
Song Track Example
-
Encapsulation Modes
-
Inline, Template inline, External Styles
-
ngClass, ngStyle
-
Shadow DOM Selectors
-
Host bindings/listeners
Blog Post
Thanks!
Advanced Component styling with Angular (v4+)
By Gerard Sans
Advanced Component styling with Angular (v4+)
In this talk we are going to cover all the different ways we can style our Angular Components. From introductory to advanced. We will learn how to style using Shadow DOM selectors, Light Dom, @HostBinding, ElementRef and more.
- 8,321