Sitemap
Sameer Khan

Sameer Khan

I am a mean stack developer with 6+ years of experience and majorly worked in Angular

Angular View Encapsulation

How does Angular View Encapsulation work

5 min readSep 11, 2022

--

What is view encapsulation in angular?

In Angular, a component’s styles can be encapsulated within the component’s host element so that they don’t affect the rest of the application.

-Angular Official Docs

In simple words, it means if you write styles for component “A” it will not affect component “B” or any other component

We have three options in view encapsulation

  • ViewEncapsulation.Emulated — (Default enabled) Encapsulate styles using attributes
  • ViewEncapsulation.ShadowDom — Encapsulate styles using the browser’s built-in Shadow DOM API
  • ViewEncapsulation.None — Don’t encapsulate styles

ViewEncapsulation.Emulated

Before we understand how emulated works, we must understand the CSS attribute selector

We have one input and a div element in vanilla HTML and CSS

To select the above input and div element in CSS, you can use its attribute

See it in action below, Click on Result

More on attribute selector here

Fine, let's come back to the angular component, If you inspect your component HTML which has ViewEncapsulation.Emulated, It will look something like this

Press enter or click to view image in full size

Notice the attributes? _nghost-* _ngcontent-* It is generated by angular while compiling the application

  • _nghost-* is added to the host element i.e app-component-a and app-component-b
  • _ngcontent-* is added to all of the content inside the components

These attributes are uniquely generated for each component that has ViewEncapsulation.Emulated

Also, notice how CSS contains these attributes, h1[_ngcontent-*] this way angular encapsulate styles and make sure they don’t affect any other component

ViewEncapsulation.ShadowDom

This encapsulation purpose is also the same(don’t bleed styles out of the component), But instead of unique attributes Angular uses the browser’s built-in ShadowDom to encapsulate component styles

If you inspect the ShadowDom enabled component HTML, it will look something like this

Press enter or click to view image in full size

Notice we don’t have that ugly attributes in HTML and as well as in CSS, If it doesn’t have unique attributes how styles are encapsulated?

Now our component contains something called shadow-root and it contains our styles which make sure it applies styles to its inside content only(not outside component)

But how does ShadowDom works?

To understand this we must understand the ShadowDom scope, In simple words, it is the same as the JavaScript scope for let and const

If ViewEncapsulation.ShadowDom works the same and doesn’t have ugly attributes then why not use it for all components?

Get Sameer Khan’s stories in your inbox

Join Medium for free to get updates from this writer.

As ShadowDom is not supported in old browsers, we cannot use it and this is the same reason Emulated is enabled by default

ViewEncapsulation.None

This option is to disable encapsulation completely for the component

This means if you write styles in the component which has ViewEncapsulation.None enabled that is like writing styles in styles.scss(Global styles)

Mostly this option will be used by third-party libraries such as Angular Material and PrimeNG

Bonus #1

We also had ViewEncapsulation.Native which is deprecated in favor of ViewEncapsulation.ShadowDom

  • ViewEncapsulation.Native — Uses ShadowDom v.0
  • ViewEncapsulation.ShadowDom — Use ShadowDom v.1

Bonus #2

What is ::ng-deep and :host?

Note: ng-deep is deprecated and there is no alternative for this currently, But you don’t have to worry, Because I believe once angular have an alternative, they will automatically replace the ng-deep when you run ng update (read ng-deep deprecation here)

::ng-deep

As you know ViewEncapsulation.None disables encapsulation completely for the entire component, Is there a way to partially disable encapsulation?

Yes, that's were ::ng-deep comes in, example below

But why do you want to do that? why do you want to disable encapsulation partially?

If you have used third-party libraries then you may have already noticed that the HTML of the third-party libraries don’t get encapsulation attributes as they have disabled it using ViewEncapsulation.None

And when we try to customize the third-party library content it won't take any effect, because our component has ViewEncapsulation.Emulated enabled

Let’s take a component with a third-party library included and customize it, The example below is having a PrimeNG button but the concept is the same for any third-party library(Angular Material for example)

Press enter or click to view image in full size
//compiled app.component.scss
.p-button[_ngcontent-*] {
background: red !important;
}

I have added the above styles to change the background of the PrimeNG button, but It doesn’t change

If you notice the above image, the PrimeNG button doesn’t have any attribute in HTML as ViewEncapsulation is disabled and my styles have attributes because ViewEncapsulation is enabled.

To solve this issue we can use ::ng-deep to partially disable encapsulation

//app.component.scss::ng-deep .p-button {
background: red !important; //not scoped, same as writing in global
}
.other-el {
color: blue; //scoped to app.component
}

Yay! Now It works

Press enter or click to view image in full size

Wait, It is applying those styles to all the components, What If I want to apply styles to a single component?

Then you can use any parent selector or :host

:host

Remember that attribute(_nghost-*) which angular adds to the component’s host element? Using this special selector you can customize the third-party library and still scope styles to the component itself, So styles don’t bleed to any other component

//app.component.scss:host ::ng-deep .p-button {
background: red !important; // scoped to app.component only
}
Press enter or click to view image in full size

Cheers🎉

--

Sameer Khan
Sameer Khan

Written by Sameer Khan

I am a mean stack developer with 6+ years of experience and majorly worked in Angular