Large Angular apps are complex and hard to maintain. Real-life applications can have hundreds of components.
The more components there are, the more tedious it gets to ensure that changes in one of them do not impact others. View encapsulation prevents such problems. It sets clear boundaries between the elements. Moreover, performance is increased with view abstraction. Angular can optimize rendering due to limited style and template changes. It can prevent unnecessary updates.
This blog will examine view encapsulation. It will cover how it works, why it’s essential, and how to apply it in building robust, scalable Angular apps.
View Encapsulation
In Angular, use the View Encapsulation feature to control component styles. It controls how styles defined in a component reach its child components and elements. A component’s styles can be inside its host element. This prevents them from affecting the rest of the app.
Modes of ViewEncapsulation
The Component decorator has three styles options. They control how styles are applied per component.
ViewEncapsulation.Emulated (default)
ViewEncapsulation.Emulated is the default mode in Angular. It uses an emulated shadow DOM to scope styles to the component. Styles defined in a component are scoped to it. They don’t affect other components or the global styles.
Component styles in <head> are app-wide. Their selectors apply only to the component’s template.
// src/app/component1.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-component1', template: ` <div style="color: red">Emulated View Encapsulation</div> `, styles: [`div { background-color: blue; }`], encapsulation: ViewEncapsulation.Emulated // Default }) export class Component1Component {}
// src/app/app.component.ts (assuming you want to render component1) import { Component } from '@angular/core'; import { Component1Component } from './component1/component1.component'; @Component({ selector: 'app-root', template: ` <app-component1></app-component1> `, styleUrls: ['./app.component.css'] }) export class AppComponent { }
In this example, Component1Component uses ViewEncapsulation.Emulated. The div within this component will have blue background and red text. The styles are scoped to this component. These will not affect or get affected by other components. So, you will get the following output.
ViewEncapsulation.None
ViewEncapsulation.None removes encapsulation, making styles global. This means that styles in the component can affect, or be affected by, other styles in the app.
Component styles are added to the <head> of the document. This makes them globally available. They can affect any matching elements in the entire document.
// src/app/component2.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-component2', template: ` <div style="color: green">None View Encapsulation</div> `, styles: [`div { background-color: yellow; }`], encapsulation: ViewEncapsulation.None }) export class Component2Component {}
// src/app/app.component.ts (assuming you want to render component1 and component2) import { Component } from '@angular/core'; import { Component1Component } from './component1/component1.component'; import { Component2Component } from './component2/component2.component'; @Component({ selector: 'app-root', template: ` <app-component1></app-component1> <app-component2></app-component2> `, styleUrls: ['./app.component.css'] }) export class AppComponent { }
In Component2Component, styles are not scoped. The div will have a green text colour and a yellow background. These styles can interact with or be overridden by other global styles or component styles. So, the output will be:
ViewEncapsulation.ShadowDom
ViewEncapsulation.ShadowDom uses the native Shadow DOM to hide styles. This mode keeps styles isolated from other components and global styles. Styles apply only to the shadow DOM host. They affect only elements within their component views.
// src/app/component3.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-component3', template: ` <div style="color: purple">Shadow DOM View Encapsulation</div> `, styles: [`div { background-color: orange; }`], encapsulation: ViewEncapsulation.ShadowDom }) export class Component3Component {} // src/app/app.component.ts (assuming you want to render component1 and component3) import { Component } from '@angular/core'; import { Component1Component } from './component1/component1.component'; import { Component3Component } from './component2/component3.component'; // typo fixed - component3 should be imported here @Component({ selector: 'app-root', template: ` <app-component1></app-component1> <app-component3></app-component3> `, styleUrls: ['./app.component.css'] }) export class AppComponent { }
With ViewEncapsulation.ShadowDom Component3Component styles are fully encapsulated. The div inside this component will have purple text and an orange background. External styles will not affect it. So, the output will be
Inspecting generated CSS
Inspect the generated CSS. It shows how Angular applies styles with different encapsulation modes. Here’s how:
Developer Tools is opened by clicking on the page, selecting Inspect, or via F12.
Locate the Element: Go to the element inside the component.
Check the Styles: Check the Styles applied in the Styles pane.
For ViewEncapsulation.Emulated, Angular adds specific attributes to the component elements. This is shown by markers like [_ngcontent-c0]. But, with ViewEncapsulation.None, styles are applied globally. They have no special attributes. For ViewEncapsulation.ShadowDom, check the Elements tab for a shadow DOM boundary.
Mixing encapsulation modes
Mixing encapsulation modes within an Angular application can be useful for different scenarios. For example, you might use ViewEncapsulation.None for global styles and ViewEncapsulation.ShadowDom for components that require strict style isolation.
// src/app/component1.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-component1', template: `<div style="color: red">Emulated View Encapsulation</div>`, styles: [`div { background-color: blue; }`], encapsulation: ViewEncapsulation.Emulated // Default }) export class Component1Component {} // src/app/component2.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-component2', template: `<div style="color: green">None View Encapsulation</div>`, styles: [`div { background-color: yellow; }`], encapsulation: ViewEncapsulation.None }) export class Component2Component {} // src/app/component3.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-component3', template: `<div style="color: purple">Shadow DOM View Encapsulation</div>`, styles: [`div { background-color: orange; }`], encapsulation: ViewEncapsulation.ShadowDom }) export class Component3Component {} // src/app/app.component.ts import { Component } from '@angular/core'; import { Component1Component } from './component1/component1.component'; import { Component2Component } from './component2/component2.component'; import { Component3Component } from './component3/component3.component'; @Component({ selector: 'app-root', template: ` <app-component1></app-component1> <app-component2></app-component2> <app-component3></app-component3> `, styleUrls: ['./app.component.css'] }) export class AppComponent { }
In this example, AppComponent renders Component1Component, Component2Component, and Component3Component, each with different encapsulation modes. This setup demonstrates how styles can be isolated or shared across components. So, the output will be:
Conclusion
View Encapsulation is a powerful Angular tool. It controls how styles and templates are hidden within components. Master the three modes: emulated, none, and shadow. Then, you can make better decisions on how to architect your Angular apps. Though Emulated is default and usually best, there are times when None or Shadow DOM may have advantages.
By carefully considering your app’s needs and using view encapsulation, you can make your Angular apps more maintainable, scalable, and predictable. To start building efficient Angular applications, sign up for Angular JS Course to learn from experts.
FAQs:
When to use view encapsulation in Angular?
You can control the scope of styles with view encapsulation. The default and most commonly used is Emulated. None is used for global styles, and ShadowDom is to be used for strict isolation.
What is ViewEncapsulation none in Angular?
ViewEncapsulation.None removes style encapsulation, allowing styles to be applied globally. This is useful if you want styles to affect or be affected by each other.
What are the different types of view encapsulation?
Angular has three types of view encapsulation: Emulated (default), None, and ShadowDom. Each affects how styles are scoped and applied within the component.
What is the default value of view encapsulation in Angular?
The default value is ViewEncapsulation.Emulated. It scopes styles to the component and protects its view with Shadow DOM.