About shadow DOM
Table of contents
Why Shadow DOM?
Shadow DOM separates content from presentation thereby eliminating naming conflicts and improving code expression.
Basic usage
The Shadow DOM spec provides a programmatic method createShadowRoot
for adding a shadow DOM subtree to an element.
When you define a Polymer element,
you can specify the contents of the element’s shadow DOM using a <template>
tag:
<polymer-element name="my-custom-element" noscript>
<template>
<span>People say: </span>
<content select="q"></content>
<footer>sometimes</footer>
</template>
</polymer-element>
The span
, content
, and footer
elements are encapsulated within
the custom element and hidden from the rest of the page.
Shadow DOM subtrees
Shadow DOM allows a single node to express three subtrees: light DOM, shadow DOM, and composed DOM.
Together, the light DOM and shadow DOM are referred to as the logical DOM. Developers interact with the logical DOM. The browser uses the composed DOM to render the pixels on the screen.
Light DOM
The user of your custom element supplies the light DOM:
<my-custom-element>
<q>Hello World</q> <!-- part of my-custom-element's light DOM -->
</my-custom-element>
The light DOM of <my-custom-element>
is visible to the end-user of the
element as a normal subtree. The end-user can access .childNodes
, .children
, .innerHTML
, or any other property or method that gives information about a node’s subtree.
Shadow DOM
<my-custom-element>
may define a shadow DOM by attaching a shadow root to
itself.
#document-fragment
<polymer-element name="my-custom-element" noscript>
<template>
<!-- Shadow DOM subtree -->
<span>People say: </span>
<content select="q"></content>
<footer>sometimes</footer>
</template>
</polymer-element>
Shadow DOM is internal to the element and hidden from the end-user.
Shadow DOM nodes are not children of <my-custom-element>
.
Note: Shadow roots are represented as a #document-fragment
in DevTools.
Composed (rendered) DOM
The composed DOM is what the browser actually renders. For rendering, the light DOM is distributed into the shadow DOM to produce the composed DOM. The final output looks something like this:
<my-custom-element>
<span>People say: <q>Hello World</q></span>
<footer>sometimes</footer>
</my-custom-element>
Nodes in light DOM or shadow DOM express parent and sibling relationships that match their respective tree structures; the relationships that exist in the composed tree are not expressed anywhere in DOM. So, while the <span>
in the final composed tree is a child of <my-custom-element>
and the parent of <q>
, it is actually a child of the shadow root and <q>
is a child of <my-custom-element>
. The two nodes are unrelated but
Shadow DOM renders them as if they are. In this way, the user can manipulate light DOM or shadow DOM directly as regular DOM subtrees, and let the system take care of keeping the render tree synchronized.