Introduction to Shadow DOM

10 / May / 2016 by Himanshu Adhikari 0 comments

Web Components consists of several independent technologies, Shadow Dom is one of them. Web components are reusable user interface widgets that are created using open Web technology. They are fully browser supported or we can say they are part of the browser, so they don’t need external libraries like jQuery or Polymer.

Web Components is a combination of four technologies :-

  1.  Custom Elements.
  2.  HTML Templates.
  3.  Shadow Dom.
  4.  HTML imports.

In this blog we’ll be focusing on shadow DOM. Currently only Chrome and Opera Browsers supports it. It provides encapsulation for styles, JavaScript and templating so that these things remains separate from rest of the DOM.

Now one question arises that why would one wants to keep some code separate from rest of the page? One reason is that on a large site, for example,  if the css is not carefully organised, then the styling for the navigation can “leak” into the main content, where it was not intended to go, or vice-versa.

Now let’s take an example to understand this problem, you all are familiar with the audio tag. Have you ever seen that your style overriding the style of audio tag. No, this is because audio tag renders its view and styling from shadow dom.

Screenshot from 2016-05-03 13:10:46

To enable shadow dom in chrome browser open Developer tools by Ctrl+Shift+I. Click on 3 vertical dots on the top right corner of dev tools before close button. Now click on settings there you will find “Show user agent shadow DOM” checkbox under the Elements section in General Tab. By checking that button it will enable shadow dom on one’s browser.

Screenshot from 2016-05-03 13:29:00

Shadow dom can be appended to any kind of HTML node (e.g., div, button, section etc). With shadow dom, element get a new kind of node associated with them, this new node is known as Shadow Root. An element that has a shadow root associated with it is called a shadow host.

Note : – The content of a shadow host isn’t rendered; the content of the shadow root is rendered instead.

For example, if you had markup like this:

[code language=”html”]
<button id="btn">Hello, world!</button>
<script>
var host = document.querySelector(‘#btn’);
var root = host.createShadowRoot();
root.textContent = ‘Hello, friends’;
</script>
[/code]

For output of above code click here

Here as we can see that instead of “hello, world”, “hello, friends” gets rendered on button. Not only that, if JavaScript on the page asks what the button’s textContent is, it isn’t going to get “Hello, friends”, but “Hello, world!” because the DOM subtree under the shadow root is encapsulated.

Content Tag

If you want to render the content of shadow host then content tag is used to accomplish this task. Demo

[code language=”html”]
<button class="red">My Button</button>
<script>
var button = document.querySelector(‘button’);
var root = button.createShadowRoot();
root.innerHTML = ‘<content></content>’;
</script>
[/code]

Content tag is similar to transclude property in Angularjs. If you want to choose which part of shadow host will be rendered by shadow root then select attribute in content tag is used. The value of select attribute can be element’s id, class name or node nameDemo

Styling the host element

The :host css property allows you to select and style the element hosting a shadow tree: Demo

[code language=”html”]
<button class="red">My Button</button>
<script>
var button = document.querySelector(‘button’);
var root = button.createShadowRoot();
root.innerHTML = ‘<style>’ +
‘:host { text-transform: uppercase; }’ +
‘</style>’ +
‘<content></content>’;
</script>
[/code]

Those are the basics of shadow dom. Shadow DOM gives us scoped style encapsulation and a means to let in as much (or as little) of the outside world as we choose. I hope you’ll agree that shadow dom is extremely powerful. For the first time we’ve proper encapsulation without extra baggage of <iframe>s.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *