Angular provides 3 options for view encapsulation:
1. Emulated (default) - styles are scoped to the component and attributes are added for specificity
2. Native - uses native shadow DOM for full encapsulation where supported
3. None - styles apply globally without encapsulation
The main advantage is fully encapsulated styles that don't clash, keeping CSS clean and organized. Angular emulates shadow DOM for wider browser support by default using attributes, but allows native encapsulation where possible.
2. Discussion Agenda
• Web Components
• Shadow DOM
• Angular View Encapsulation
• 3 Types Examples
2
3. Background: Web Components
“Web Components are a set of features currently being added by the W3C to the HTML and DOM specifications
that allow for the creation of reusable widgets or components in web documents and web applications. The
intention behind them is to bring component-based software engineering to the World Wide Web.”
Basically, the Web Components browser feature is the World Wide Web Consortium’s basic implementation of a
JavaScript framework in the browser.
Web Components consist of 4 main features which can be used separately or all together:
• Custom Elements – APIs to define new HTML elements (looks a lot like Angular, React, etc.. )
• Shadow DOM – Encapsulated DOM and styling, with composition
• HTML Imports – Declarative methods of importing HTML documents into other documents
• HTML Templates, an HTML fragment is not rendered, but stored until it is instantiated via
JavaScript (React – ish)
3
4. Background: Shadow DOM
• Shadow DOM is a feature of HTML 5 Web Components allowing a component to encapsulate its
implementation, including styling
• Shadow DOM is a functionality that allows the web browser to render DOM elements without putting them into
the main document DOM tree.
• This creates a barrier between what the developer and the browser can reach:
1. The developer cannot access the Shadow DOM in the same way she would with nested elements (DOM
tree traversal, data closures, etc)
2. The browser can render and modify that code the same way it would with nested elements.
• Result = DOM Tree and Style Encapsulation!
Shadow DOM lets us hide DOM logic behind other
elements to encapsulate functionality.
Shadow DOM also lets us apply scoped styles to our
local element without the rest of the app being
affected.
4
5. Shadow DOM Rendering Process
1. A component is instantiated in markup by the developer. This is called the Shadow Host.
2. Using Shadow DOM, at load time, the browser creates a Shadow Root and Shadow Tree for each
component instantiated.
3. At render time, the browser inserts the Shadow Tree into the DOM with the Shadow Host at the root.
Think “Transclusion” in Angular JS!
5
6. Big Picture: What is the advantage of using Shadow DOM?
Shadow DOM allows us to build components with fully encapsulated DOM logic,
including styles which only apply to our element!
This lets us keep our app’s CSS cleaner and our markup more organized.
(in the author’s opinion)
We can also use 3rd party components without any risk of CSS name clashing.
Example: Using the HTML 5 native datepicker input element below,
we can render an entire functional datepicker.
< input type = “date” >
6
7. Angular View Encapsulation – 3 Types
View encapsulation defines whether the template and styles defined within
the component can affect the rest of the application, or whether the template
and styles are isolated to the component.
Angular provides 3 options for View Encapsulation:
1. Emulated (default) - styles from main HTML propagate to the
component. Styles defined in this component's @Component decorator
are scoped to this component only.
2. Native - styles from main HTML do not propagate to the component.
Styles defined in this component's @Component decorator are scoped
to this component only.
3. None - styles applied to the component are written to the document
head and visible to the entire app.
Be careful when using None and Native components together in the
application. All components with ViewEncapsulation = None will have their
styles duplicated in all components with View Encapsulation = Native
7
Notice that Angular
does not use the
native browser
Shadow DOM by
default but instead
uses an emulated
Shadow DOM!
8. Example: ViewEncapsulation = None
Angular doesn’t use Shadow DOM at all. Styles applied to our component are written to the document head.
All of the styles apply to the entire document.
A component could overwrite styles from another component because its styles are applied to the document head later.
import {ViewEncapsulation} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-zippy',
templateUrl: 'my-zippy.component.html',
styles: [ `.zippy { background: green; }’ ],
encapsulation: ViewEncapsulation.None
})
class ZippyComponent {
@Input() title: string;
}
<div class="zippy">
<div (click)="toggle()" class="zippy__title">
</div>
<div [hidden]="!visible" class="zippy__content">
<ng-content></ng-content>
</div>
</div>
8
<html>
<head>
<style>
.zippy {
background: green;
}
</style>
</head>
<body>
<my-zippy title="Details">
<div class="zippy">
<div (click)="toggle()" class="zippy__title">
▾ Details
</div>
<div [hidden]="!visible" class="zippy__content">
<script type="ng/contentStart"></script>
...
<script type="ng/contentEnd"></script>
</div>
</div>
</my-zippy>
</body>
</html>
Shadow DOM creates
content insertion points out of
script tags as placeholders for
ng-content projection
9. Example: ViewEncapsulation = Emulated
9
This view encapsulation is used by default. ViewEncapsulation.Emulated emulates style encapsulation, even if no
Shadow DOM is available in the browser.
The common use case is for third-party components which come with styles that might cause a name clash with
local CSS.
1. Angular emulates Shadow DOM by augmenting styles with CSS attribute selectors before writing them to
the document head.
2. Angular creates encapsulation by then adding matching attributes to the template HTML, ensuring higher
specificity than other CSS in the app.
• The emulated Shadow Host DOM node is marked with
_ng-host-* (and so on)
• Emulated Shadow Tree content DOM nodes are
marked with _ngcontent-* attributes, starting with ng-
content-0 at the Shadow Root DOM node.
• What happened to ng-host-0 ? This is assumed to be
the app root.
Content Insertion points are marked with the
_ngcontent-* attribute by the framework!
Remember that CSS
matches attributes using [ ]
11. Example: ViewEncapsulation = Native
Using Native view encapsulation, Angular uses the Shadow DOM in the browser.
No extra attributes are added!
Note that you need to enable Shadow DOM inspection on dev tools, however.
11
import {ViewEncapsulation} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'my-zippy',
templateUrl: 'my-zippy.component.html',
styles: [ `.zippy { background: green; }’ ],
encapsulation: ViewEncapsulation.Native
})
class ZippyComponent {
@Input() title: string;
}
<div class="zippy">
<div (click)="toggle()" class="zippy__title">
</div>
<div [hidden]="!visible" class="zippy__content">
<ng-content></ng-content>
</div>
</div>
<my-zippy title="Details">
#shadow-root
| <style>
| .zippy {
| background: green;
| }
| </style>
| <div class="zippy">
| <div (click)="toggle()" class="zippy__title">
| ▾ Details
| </div>
| <div [hidden]="!visible" class="zippy__content">
| <content></content>
| </div>
| </div>
"This is some content"
</my-zippy>
12. Summary
Angular does not use Shadow DOM for View Encapsulation by default. Angular will Emulate Shadow DOM to
implement View Encapsulation unless we tell it otherwise with configuration.
View Encapsulation is great because it allows for scoped CSS which lets us keep our CSS cleaner and more organized,
and use 3rd party components without risk of name clashing.
Angular emulates Shadow DOM View Encapsulation by adding attributes to the template, marking nodes on the
Shadow Tree as content insertion points, and marking the Shadow Host as a host node.
Angular takes advantage of the CSS attribute selector [ ] to add specificity to CSS classes, thus scoping our styles.
Angular adds attribute selectors to encapsulated styles which match the attributes added to the template.
Native View Encapsulation is much simpler, and no attributes are added, however browser support is not universal.
12