Before even going into what, when and how, let’s ask ourselves why do we even bother to learn about this strange thing that call itself - Shadow DOM.
Great start! Web Component standards encourage to use more of a reusable widget/component based approach. But there is a fundamental problem that makes widgets built out of HTML and JavaScript hard to use -
The DOM tree inside a widget isn’t encapsulated from the rest of the page. This lack of encapsulation means your document stylesheet might accidentally apply to parts inside the widget; your JavaScript might accidentally modify parts inside the widget; your IDs might overlap with IDs inside the widget; and so on.
Thus, Shadow DOM addresses the DOM tree encapsulation problem.
What is Shadow DOM?
With Shadow DOM, elements can get a new kind of node associated with them. This new kind of node is called a shadow root. An element that has a shadow root associated with it is called a shadow host. The content of a shadow host isn’t rendered; the content of the shadow root is rendered instead.
By default usual styling won’t get applied here i.e. it only works for main DOM tree but not for shadow trees. For it, we can do something like
shadow.innerHTML = '<style>p { color: red; }</style>';
:host allows you to select and style the element hosting a shadow tree.
shadow.innerHTML = '<style>:host { text-transform: uppercase; }</style>';
Better roads with <template>
Content and presentation
As soon as the shadow host’s content changes, shadow DOM will be updated automatically. By separating content and presentation, we can simplify the code that manipulates the content.
The content is in the document; the presentation is in the Shadow DOM. They are automatically kept in sync by the browser when it comes time to render something. Also, now since we have isolated the content from presentation, we can change our presentation and the content doesn’t need to know about it.
Advance <content>
select can only select elements which are immediate children of the host node. That is, you cannot select descendants (e.g. select="table tr").
Content once selected, cannot be selected again.
Styling host
Piercing through the shadow DOM’s boundary
The ruthless /deep/
Completely ignores all shadow boundaries and crosses into any number of shadow trees.
The /deep/ combinator is particularly useful in the world of Custom Elements where it’s common to have multiple levels of Shadow DOM. Prime examples are nesting a bunch of custom elements (each hosting their own shadow tree) or creating an element that inherits from another using <shadow>.
Shadow DOM traversal
Does all of this apply on native elements too?
Native HTML controls are a challenge to style. With ::shadow and /deep/, any element in the web platform that uses Shadow DOM can be styled.
::content pseudo element
User states (:hover, :focus, :active, etc.)
Theming
The :host-context(<selector>) pseudo class matches the host element if it or any of its ancestors matches <selector>
Multiple Shadow DOMs
Obviously later one will replace the previous one.
Shadow insertion points (<shadow>) are similar to normal insertion points (<content>) in that they’re placeholders. However, instead of being placeholders for a host’s content, they’re hosts for other shadow trees.
Reference to previous tree root2.olderShadowRoot === root1; //true