View Encapsulation in Angular

Shubham Akodiya
GAMMASTACK
Published in
6 min readJan 14, 2020

We often forget the use of a great feature of Angular — View Encapsulation. Let’s dive inside it to understand how Angular handles things for us behind the scenes:

  • How Angular protects styles of custom components from being overridden by other components?

In simple HTML, if we try to write the same styles using classes, ids or element, styles may get overridden unless we’re using the parent-child element selectors, but why the same thing does not happen with Angular, even though, in the end, both are using the same DOM. (Angular provides the shadow DOM feature, more on this later)

  • How can we change this default behavior of Angular?

What is View Encapsulation?

As the name suggests encapsulation refers to show only declaration part and hide the functionality. Same way, view encapsulation means the ways to encapsulate the component styles. Angular provides following features of view encapsulation:

  • Emulated (default feature)
  • None
  • Shadow DOM

To add the encapsulation type, we need to do following:

View Encapsulation: Emulated

This is the default view encapsulation option for Angular. Angular uses this option to protect component styles from getting overridden. Now it’s time to wait for a moment and think about the following —

Don’t lose confidence because even if you stumbled, you’re still moving forward.

  • What additional thing that Angular is implementing for us?
  • Is Angular changing the classes names to make them unique?
  • But what happens when we using the same className for multiple components?
  • If so, then which parameter is Angular appending with the className to make it unique and what is the reference of taking the parameter to make it unique?

Time out !!

To demonstrate what actually happens with the DOM, I’ve created one application on stackblitz. Use the below links:

As you can see, inside the emulated folder, there are following components:

  • emulated-first-component
  • emulated-second-component

Both components are using different styles for the h1.

Application view -

Here, As you can see, even though we have applied different CSS for the same element, both styles work differently. Let’s quickly dive into the inspect element console to see the styles.

As you can see, additional attributes have been added in h1 style of both the components. It makes scoped component styles and that’s the concept angular is using to encapsulate the styles.

// For emulated-second-component

h1 [_ngcontent-que-c3] { color: green}

// For emulated-first-component

h1 [_ngcontent-que-c2] {color: red}

Here some special things to notice about the attributes in Emulated view encapsulation:

  • Angular appends attributes from the root.
  • Parent component attribute starts from _nghost_que_c0 (here c0, because it is the root component and que is just a text to make the combination more unique)
  • Child component attribute starts from _ngcontent_que ( c0, c1 or c2 depends on the component sequence)
  • We can have multiple _nghost_que components in the child component. You can take the example of emulated-first and emulate-second components, in which _nghost_que_c1 and _nghost_que_c2 have been added.
  • We can add styles using these unique attributes, like

<style>

[_nghost-c0] h2 {

color: red;

}

</style>

For further clarification, Please have a look at the below image

View Encapsulation: None

If we don’t want to add additional attributes to the styles of the component as shown above then we can use this encapsulation type. To use this encapsulation type, please have a look at the below screenshots.

Now, if we don’t have the unique attribute attached to the component styles then component styles may be overridden by other components.

Styles in this approach are not scoped and all styles goes inside the <style> </style> tag, as you would expect in simple HTML.

I’ve added none encapsulation type for both the components, as you can see in the above screenshots. Now you can check the changes in the view.

As you can see, h1 style of the emulated-second-component is overwritten to other components.

View Encapsulation: Shadow DOM

Shadow DOM, allows a component to have its very own shadow DOM tree and it will be isolated from any other component. In other words, we can say, each component has its own scope. You can think of shadow DOM as a scoped sub-tree inside your element. Please visit this link for more info regarding the shadow DOM.

Please have a look at the basic example of shadow DOM:

<div class=”shadow-dom1">
<span>Light DOM Example — shadow-dom1</span>
</div>
<div class=”shadow-dom2">
<span>Light DOM Example — shadow-dom2</span>
</div>

On the JS side, for creating the shadow DOM, I’ve used below code:

const element1 = document.querySelector(‘.shadow-dom1’);
element1.attachShadow({ mode: ‘open’ });
element1.shadowRoot.innerHTML = `
<style>
span {
color: green;
}
</style>
<span>Shadow DOM</span>
<slot></slot>
`;

const element2 = document.querySelector(‘.shadow-dom2’);
element2.attachShadow({ mode: ‘open’ }); //
element2.shadowRoot.innerHTML = `
<style>
span {
color: red;
}
</style>
<span>Shadow DOM</span>
<slot></slot>
`

So here, we have done the following -

  • We’ve added the shadow DOM inside both div elements ‘shadow-dom1’ and ‘shadow-dom2’.
  • Both elements’ shadow DOM contain the span with a different style.

Code pen link for this example: https://codepen.io/shubhamak123/pen/GRgdaPO

As clearly seen from the screenshot that shadow DOM creates isolate scope for span elements inside both the divs.

In Angular, if we use encapsulation type as ‘ShadowDOM’ then we have the isolated scopes for each of the components same as above. You can check the below screenshot, in which, shadow-root document has attached to the component.

As per the MDN doc, Shadow DOM is supported by default in Firefox (63 and onwards), Chrome, Opera, and Safari. The new Chromium-based Edge (75 and onwards) supports it too; the old Edge didn’t.

--

--