A few days ago I wrote about Angular ViewEncapsulation. The sample I’ve created for that post only works if you’re using Google Chrome. In this article, I’ll explain why the sample only works in Google Chrome and how you can take the example one step further to work and behave as expected in all modern browsers.
Angular is using ViewEncapsulation.Emulated
by default, to render components. Emulated
means you’re not using native ShadowDOM
features; instead Angular does some refactoring to both, your template and your styles, to encapsulate those from the rest of your app and render everything as expected. (see the linked article above for more details).
This emulation mode is also used if the browser (Google Chrome) has built-in support for ShadowDOM
. If you force Angular to use Native
view encapsulation for your components, the component decorators have to look like this:
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'todo-item',
templateUrl: 'todoitem.html',
styleUrls: ['styles/todoitem.css']
encapsulation: ViewEncapsulation.Native
})
export class TodoItemComponent {
}
Angular relies on official ShadowDOM
specs and let browsers decide how to deal with your components. Everything works fine in Google Chrome and Opera, but unfortunately, there are more browsers in the wild.
Both Chrome and Opera are supporting ShadowDOM
without using any polyfills
. However, when users visit your app with browsers like Microsoft Edge or Mozilla Firefox or Apple’s Safari, they will see just nothing because those browsers neither have any native implementation for ShadowDOM
nor are they shipping any polyfill out of the box. Angular tries to render your app and it will crash as soon as the ShadowDOM
API will be called by the Angular core framework.
To get ViewEncapsulation.Native
working across all browsers, you’ve to put another JavaScript dependency in your website by adding a script reference to WebComponentsJs.
WebComponentsJs
adds the required polyfills at runtime (only if the browser doesn’t provide some), so Angular can call into ShadowDOM APIs. Some of you may also know Polymer
project which was also targeting the same issue.* Polymer is now part of WebComponentsJs
, so you don’t have to make a decision here.