Dzhavat Ushev

Twitter GitHub RSS

“ViewEncapsulation” in Angular

Ah, ViewEncapsulation!

It’s what keeps you asleep through the night! Or does it? 😊

Let’s refresh our knowledge about ViewEncapsulation.

ViewEncapsulation.Emulated

By default, all Angular components come with something called “style encapsulation”. It means that a component “encapsulates” its own styles so they only apply to elements within its scope. Styles defined in one component will not have an effect on the elements in another component.

Angular achieves this by adding a specific attribute to the component’s host element and applying the same attribute to all the CSS selectors provided via Component#styles or Component#styleUrls. (taken from Angular’s docs)

Considering a component to be an independent unit, this is the expected behaviour. You don’t want your components to “leak” styles that affect “outside” elements.

The above is done by setting the Component.encapsulation option to ViewEncapsulation.Emulated (or not setting it at all since that’s the default value).

Looking at the DevTools in the Figure 1 below, you can see that the my-app component has a _nghost-ng-<id> attribute. The same <id> is also added to the _ngcontent-ng-<id> attribute present on all child elements.

Figure 1: How ViewEncapsulation.Emulated works in Angular

Note that the <id> is auto-generated by Angular and you should not rely on it being the same every time. So don’t style elements with _ngcontent-ng-abc123!

ViewEncapsulation.None

View encapsulation can be turned off on a component by setting the Component.encapsulation option to ViewEncapsulation.None.

But beware! Turning view encapsulation off means that all of the component’s styles now apply globally. They will no longer be scoped to the component, and can therefore affect any HTML element in the application.

You can see that by inspecting the component’s elements in DevTools:

Figure 2: How ViewEncapsulation.None works in Angular

Figure 2 above shows us that the _nghost-ng-<id> attribute is no longer present on the my-app component, nor on any child elements. Styles added to h1 will now “leak” from the component and affect any other h1s on the page. Had there been another h1 on the page, even in a completely different component, the color: tomato style would be applied to it.

There are valid reasons for turning encapsulation off, e.g. styling 3rd party components, or because parts of a component are dynamically created/moved to some other part of the DOM, e.g. a modal that is created as a child to body. Whatever the case, beware that the styles you add to a component might have an effect on unrelated elements!

But what if you want to disable view encapsulation on a component but still keep some, or all of its styles scoped to the component?

You can achieve this by nesting the styles under the component’s selector, i.e.

my-component {
  h1 {
    color: tomato;
  }
}
Figure 3: Component with ViewEncapsulation.None with styles scoped to the component

ViewEncapsulation.ShadowDom

Component.encapsulation can take a third value - ViewEncapsulation.ShadowDom but so far I’ve never used it in my apps. Once set, it uses the browser’s native Shadow DOM API to encapsulate CSS styles, … (taken from Angular’s docs).

It looks like this in DevTools:

Figure 4: How ViewEncapsulation.ShadowDom works in Angular

I don’t have experience with ShadowDom, so I’ve included it only for reference. You can decide for yourself whether it makes sense to use it in your apps.

Well, that’s it! I hope you learned something new about style encapsulation in Angular.

See you in the next post 👋

Share on Twitter