Styling and view encapsulation
Each component has its own styles, and by default they apply only to its template. This is called style encapsulation: a .done class in the to-do list will not spoil a button with the same class in another component. Rules for the whole site go into a separate file.
Component styles
The stylesheet sits next to the component and is attached with styleUrl:
/* src/app/todo-item/todo-item.css */
.done {
color: gray;
text-decoration: line-through;
}<!-- src/app/todo-item/todo-item.html -->
<span [class.done]="todo().done">{{ todo().title }}</span>A completed task turns gray and struck through. Elements with the done class in other components are not affected by this rule.
How it works
In the default mode Angular adds an attribute like _ngcontent-abc-c12 to template elements, and the same condition to the CSS selectors. Open the developer tools — the span tag has this attribute, and the rule looks like .done[_ngcontent-abc-c12].
encapsulation mode | Behavior |
|---|---|
ViewEncapsulation.Emulated | Default: styles only for its own template |
ViewEncapsulation.None | Styles become global |
ViewEncapsulation.ShadowDom | The browser's real Shadow DOM |
The mode is set in the decorator: encapsulation: ViewEncapsulation.None (ViewEncapsulation is imported from @angular/core). You rarely need to change it.
Global styles
Fonts, colors and margin resets go into src/styles.css — this file is attached to the whole application:
/* src/styles.css */
body {
margin: 0;
font-family: system-ui, sans-serif;
}
a {
color: #1d4ed8;
}These rules apply to all components.
The :host selector
:host is the component's own tag, for example app-todo-item. By default such a tag is inline, and it is often given block display:
/* src/app/todo-item/todo-item.css */
:host {
display: block;
padding: 8px 0;
border-bottom: 1px solid #eee;
}Each task becomes a separate row with a line underneath.
Classes and styles from data
Besides [class.name] and [style.property] there are bindings to several values at once:
<!-- src/app/todo-item/todo-item.html -->
<span [class]="{ done: todo().done, urgent: todo().title.includes('!') }">
{{ todo().title }}
</span>
<span [style.font-size.px]="16">Size in pixels</span>The object in [class] turns on every class whose value is true. The .px suffix in a style binding adds the unit.
Common mistake
Trying to style elements inside a child component from the parent's styles: the rule app-todo-item span in todo-list.css will not work — the span belongs to another template. Style an element in its own component's stylesheet, and from outside change only the component tag itself or pass an input. The old workaround ::ng-deep is deprecated.