What is shadow dom?
Shadow dom can provide encapsulation for the DOM and CSS in the web component, in fact, when the browser renders the document, the written DOM element will be inserted into the specified DOM structure, but the inserted Shadow DOM will be kept with the DOM of the main document. Detached, that is, the Shadow DOM does not exist on the main DOM tree.
And the DOM elements encapsulated by Shadow DOM are independent, the external configuration will not affect the internal, and the internal configuration will not affect the external.
Why some tags we use are obviously empty elements, but they can render various complex scenes?
- input
- video
- audio
- textarea
- …
You may not have thought about why these tags different from our commonly useddiv
tags. They can render the corresponding styles and functions by simply writing a tag;
Acturally this is all about the underlying rendering, and we don’t need to care.
View the Shadow DOM of the HTML native tag
Write the following tags in html, and then go to the browser console to view
<input type="text">
<input type="range">
<video src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" controls></video>
<textarea></textarea>
Code language: HTML, XML (xml)
A lot of people see this, but it’s no different from what we wrote? Don’t worry, I’ll take you to see their true colors~

First open the settings option of the browser console

Then find Preference -> Elements and check show user anent shadow dom

Then let’s take a look at what happened to the DOM element at this time

We will find that there is a lot of space inside these tags, and there is a shadow root under these tags, which is the real layout of these tags.
Since these tags have some sub-element layouts inside, can we access them through JavaScript?
const input = document.querySelector('input')
console.log(input.firstChild) // null
Code language: JavaScript (javascript)
Obviously, this is not possible!
Because it sets a boundary for web developers about what you can access and what implementation details are not. However, the browser itself is free to cross this boundary at will. With such a border in place, they can use familiar web technologies, the same HTML elements, to create more functionality where you can’t see them
Shadow dom structure
Shadow DOM allows to attach a hidden DOM tree to a regular DOM tree – it starts with a shadow root node as the root node, and below this root node, can be any element, just like normal DOM elements.
Because of this feature , we can see that a single empty tag above can render a variety of complex scenes

The above picture is a very intuitive representation of the shadow dom structure and its relationship with normal dom.
Shadow host
A regular DOM node to which the Shadow DOM will be attached.
Shadow bounday
Where the Shadow DOM ends is also where the regular DOM begins.
Shadow tree
The DOM tree inside the Shadow DOM.
Shadow root
The root node of the Shadow tree.
How to use shadow dom?
Create a shadow dom
We can use attachShadow
to mount one shadow dom to the specified element and return a reference to the shadow root.
const shadowroot = root.attachShadow({mode: 'open'})
const template = `
<div>FrondEnd</div>
`
shadowroot.innerHTML = template
Code language: JavaScript (javascript)
Shadow dom mode
When calling Element.attachShadow()
method, you must specify the encapsulation mode
of the shadow DOM tree by passing an object as a parameter, otherwise it will throw one TypeError. The object must have a mode property with the value open or closed.
open: The shadow root element can access the root node from outside js, for example using Element.shadowRoot
:
element.shadowRoot;
Code language: CSS (css)
closed: Deny access to closed shadow root node from outside js
element.shadowRoot;
Code language: CSS (css)
Browsers often use a closed shadow root to make certain elements’ implementations inaccessible internally and not changeable from JavaScript.
For some web components that don’t want to expose the shadow root, the closed shadow DOM may seem very convenient, but bypassing the closed shadow DOM is not difficult in practice
Which elements can mount shadow dom?
It should be noted here that not all html elements can mount shadow dom, only the following elements can act as shadow host of shadow dom
**div footer h1 h2 h3 h4 h5 h6 section span **
When we try to hang on the shadow dom on other elements, the browser will throw an exception.
const input = document.querySelector('input')
const inputRoot = input.attachShadow({mode: 'open'})
Code language: JavaScript (javascript)

Features of shadow dom
From the previous introduction, we know that shadow dom is a node tree outside the DOM tree, but it is created based on ordinary DOM elements (non-documents), and the created Shadow-dom node can be seen intuitively from the interface . The most important point is that Shadow-dom has a good seal.
Style
<style>
.wx_name {
color:aqua;
}
</style>
<body>
<div class="wx_name">Real dom</div>
<div id="root"></div>
<script>
const shadowroot = root.attachShadow({mode: 'open'})
const template = `
<div class="wx_name">shadow dom </div>
`
shadowroot.innerHTML = template
</script>
</body>
Code language: HTML, XML (xml)
It renders like this👇:
We said above that the shadow dom is a node tree outside the DOM tree, so the CSS on our document will not act on it.
Style the host element
The host
pseudo-class selector allows you to access the shadow host from anywhere in the shadow root
const shadowroot = root.attachShadow({mode: 'open'})
const template = `
<div class="wx_name">shadow dom - </div>
<style>
:host {
border: 1px solid #ccc;
color: pink;
}
</style>
`
shadowroot.innerHTML = template
Code language: HTML, XML (xml)
Note that :host
only works within the shadow root, and that style rules defined outside the shadow root have a higher specificity than those defined in :host
Style hook
Another very important feature of shadow dom is that it can be used CSS sefl defined attribute to create styled placeholders and allow users to fill them.
<style>
#root {
--bg: coral;
--color: #fff:
}
</style>
<div id="root"></div>
<script></script>
Code language: HTML, XML (xml)

Access shadow via CSS
What if we want to customize the styles of some native tags, obviously regular CSS selectors cannot get elements inside shadow dom. So there’s nothing we can do about it? In fact, we can achieve this through some pseudo-elements, such as:
<input type="range">
Code language: HTML, XML (xml)
It looks like this by default
So how do we change his style, such as changing its background color
Is it possible to write the background color directly to the input?
input{
background: #ccc;
}
Code language: CSS (css)
so how can it change its background color for this one element? it has a shadow dom inside it
input[type=range]::-webkit-slider-runnable-track {
-webkit-appearance: none;
background-color: chocolate;
}
Code language: CSS (css)
We can access the shadow’s inner element and change its style through pseudo-elements.

Event
An event fired inside the shadow DOM can cross the shadow boundary and bubble up to the light DOM; however the value of Event.target
is automatically changed. so it appears as if the event originated from the shadow tree, it contains rather than the actual element’s host element.
This change is called event redirection and the reason behind it is to preserve shadow DOM encapsulation.
<div id="root"></div>
<script></script>
Code language: HTML, XML (xml)
When clicking on any element in the shadow dom, what is printed is root . the listener cannot see the real element that dispatched the event.