Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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 modeBehavior
ViewEncapsulation.EmulatedDefault: styles only for its own template
ViewEncapsulation.NoneStyles become global
ViewEncapsulation.ShadowDomThe 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.

Thanks for reading!

Donate to the site — we work hard for you.