What Is ViewEncapsulation in Angular?
In Angular, component CSS styles are encapsulated into the component’s view and don’t affect the rest of the application.
As we know Angular Components are made up of three things:
- Component Class
- Template
- Style
The combination of these three factors makes an Angular component reusable across an application. Angular also provides these feature for Components and we can control it with the encapsulation
property.
We can set the view encapsulation mode in the component metadata to control how this encapsulation happens on a per component basis.
The valid values for this config property are:
ViewEncapsulation.ShadowDom
ViewEncapsulation.Emulated
ViewEncapsulation.None
The default value is ViewEncapsulation.Emulated
To understand ViewEncapsulation in Angular, first, we should understand the Shadow DOM. Simply put, the Shadow DOM brings Encapsulation to HTML Elements. Using the Shadow DOM, markup, styles, and behaviors are scoped to the element and do not clash with other nodes of the DOM. The Shadow DOM is part of Web Components, which encapsulates styles and login of the element.
Let’s try to understand it using an example:
ViewEncapsulation.None:
Let’s create a component as component1:
component1.component.ts:
To understand different ViewEncapsulation
options, we will add the metadata as encapsulation: ViewEncapsulation.None to component1
.
import {Component, OnInit, ViewEncapsulation} from'@angular/core';@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.scss'],
encapsulation: ViewEncapsulation.None
})export class Component1 implements OnInit {
constructor() { }
ngOnInit(): void {}
}
component1.component.css:
h1 {
background: gray;
color: white;
text-transform: capitalize;
text-align: center;
width: max-content;
padding: 30px;
}
component1.component.html:
<h1>Test Encapsulation component1</h1>
Let’s create another component as component2:
import { Component, OnInit } from '@angular/core';@Component({
selector: 'app-component2',
templateUrl: './component2.component.html',
styleUrls: ['./component2.component.scss']
})
export class Component2 implements OnInit {
constructor() { }
ngOnInit(): void {}
}
component2.component.html:
<h1>Test Encapsulation component2</h1>
In component2
, we are also using the h1
tag.
In ViewEncapsulation.None:
- There is no shadow DOM.
- Style is not scoped to the component.
As we run the application, we will find h1
style has applied to both components, even though we only set style the in component1
. This happened because in component1
we have set the encapsulation property to ViewEncapsulation.None
Kindly check the screenshot below forViewEncapsulation.None:
ViewEncapsulation.Emulated:
Now if we changed the ViewEncapsulation mode to emulated which is the by default option, the output will be different.
- Angular will not create a Shadow DOM for the component.
- The style will be scoped to the component.
- This is the default value for encapsulation.
component1.component.ts:
import {Component, OnInit, ViewEncapsulation} from'@angular/core';@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.scss'],
encapsulation: ViewEncapsulation.Emulated
})export class Component1 implements OnInit {
constructor() { }
ngOnInit(): void {}
}
We have changes the encapsulation in component1.component.ts only and the rest of the things remain the same.
Let’s run the application now, we will find the h1
style changes in component1 only, not in component2. This is due to emulated scoping.
In this, the style is scoped only to the component. In this option, Angular only emulates the Shadow DOM and does not create a real shadow DOM. Hence, the application that runs in browsers does not support a Shadow DOM also and styles are scoped to the component as well.
Kindly check the screenshot below forViewEncapsulation.Emulated:
ViewEncapsulation.ShadowDom:
Now if we changed the ViewEncapsulation mode to ShadowDom, the output will be different.
- Angular will create Shadow DOM for the component.
- Style is scoped to the component.
component1.component.ts:
import {Component, OnInit, ViewEncapsulation} from'@angular/core';@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.scss'],
encapsulation: ViewEncapsulation.ShadowDom
})export class Component1 implements OnInit {
constructor() { }
ngOnInit(): void {}
}
We have changes the encapsulation in component1.component.ts only and the rest of the things remain the same.
Let’s run the application now, Here Angular is using the shadow DOM because of ViewEncapsulation.ShadowDom
Now, if we look at the application h1
changes will be applied to component1 only. The angular renders the component inside the #shadow root
element. The styles from the component along with the styles from the parent and other components are also injected inside the shadow root
According to angular.io,
Native
is now deprecated in favor ofShadowDOM
implementation. The reason for the change is that theNative
ViewEncapsulation uses the deprecated version of ShadowDOM, and the new one uses the current version of the standard. (For the browsers that support it).
NOTE: To know more about shadow DOM, Kindly check this: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
Thanks for Reading!!!!!!!!