The Shadow DOM: encapsulate code

The Shadow DOM: encapsulate styles and scripts

Encapsulate CSS and JS code in your templates, and hide theM USING Shadow DOM

By mixing templates and the shadow DOM, it is possible to hide a template’s content by embedding it in the shadow root. In this scenario, it’s easy to encapsulate CSS styles and/or JavaScript code so that it will affect only the content of the shadow root. Conversely, external CSS will not apply inside the shadow root.

This is an important feature: the content of a new “widget” that is hidden in a shadow root is protected from external CSS, scripts, etc.

an Example that mixes templates and shadow DOM:

HTML part:

  1. <template id=“mytemplate”>
  2.    <style>
  3.      h1 {color:white; background:red}
  4.    </style>
  5.    <h1>This is a shadowed H1</h1>
  6. </template>

The JavaScript part:

  1. // Instanciate the template
  2. var t = document.querySelector(‘#mytemplate’);
  3. // Create a root node under our H1 title
  4. var host = document.querySelector(‘#withShadowDom’);
  5. const shadowRoot = host.attachShadow({mode: ‘open’});
  6. // insert something into the shadow DOM, this will be rendered
  7. shadowRoot.appendChild(document.importNode(t.content, true));

Online example at JSBin:

shadow dom 3

Note that once again, the content shown is the shadow root + the styles applied. The styles applied are those defined in the template’s contentthat has been cloned and put inside the shadow root.

NB a little bit of French squeezed past our filters. “Instanciate” in French (and other languages) means “Instantiate” in English. We hope you’ll translate, as appropriate; but if you seek definitions or use the word in web-searches, then the English spelling will help!

Internal CSS will not apply outside the template/shadow DOM

The CSS inside the template will not affect any other H1 elements on the page. This CSS rule (lines 2-4 in the HTML part) will only apply to the template’s content, with no side-effects on other elements outside. 

Look at this example at JSBin that uses two H1s in the document: one is associated  with a shadow root (defined in a template with an embedded CSS that selects H1 elements and makes them white on red); whereas the other is located in the body of the document and is not affected by the CSS within the Web Component.

Beware: the included polyfill will not emulate CSS encapsulation. To see the real behavior, try with Chrome or Opera!

The HTML part:

  1. <template id=“mytemplate”>
  2.    <style>
  3.      h1 {color:white; background:red}
  4.    </style>
  5.    <h1>This is a shadowed H1</h1>
  6. </template>
  7. <body>
  8.    <h1 id=“withShadowDom”>This is a text header</h1>
  9.    <h1>Normal header with no shadow DOM associated.</h1>
  10. </body>

We added a new H1 at line 11

And here is the result:

shadow dom 4

The second H1 is not affected by the CSS defined in the template used by the first H1. Try to add this CSS rule to this example :

  1. h1 {
  2.     color:green;
  3. }

And you should see something like that:

The global CSS rule will affect the H1 in the body of the document, not the one in the shadow DOM.

In which the “regular” CSS rule changed the color of the H1 located in the body of the document, not the color of the H1 encapsulated in the Shadow DOM.

Leave a comment