What is the Shadow DOM?

Before you navigate a website, the browser interprets the HTML code and creates the DOM (Document Object Model). I always imagine the browser building a Lego using HTML, CSS, and JavaScript.

For example, let's imagine that we want to build a car using the browser. All the car pieces are in the HTML file: engine, tires, the body of the vehicle, etc. Then, you'll find the form and colors of all the previous Lego pieces on the CSS file. The JavaScript files define how motor parts react depending on the driver's actions.

If the DOM contains all these pieces, what is the Shadow DOM? Intuitively, we could think that the Shadow DOM defines hidden parts. However, this is not accurate. The hidden car parts can be well defined, even if the eye can't see those parts. For example, you could define the color of the seat's inner cushions even if they aren't visible.

The formal definition could be:

The Shadow DOM is a mechanism for isolating DOM mutations from the rest of the page

The Shadow DOM is useful to define elements that don't follow the general rules of a specific element. For example, you could use the Shadow DOM to apply different colors to a tire's logo, depending on the wheel brand.


<div class = 'Wheels'>
    <div class = 'Wheel' id = 'Wheel-1'>
        <style>.text{ color: red }</style>
        <p class = 'text'>Pirelli</p>
    <div class = 'Wheel' id = 'Wheel-2'>
        <style>.text{ color: blue }</style>
        <p class = 'text'>GoodYear</p>
    <div class = 'Wheel' id = 'Wheel-3'>
        <style>.text{ color: black }</style>
        <p class = 'text'>Michellin</p>
    <div class = 'Wheel' id = 'Wheel-4'>
        <style>.text{ color: green }</style>
        <p class = 'text'>Dunlop</p>

Notice how the wheels will have a common design:

    border-radius: 50%;
    height: 48.26cm;
    width: 48.26cm;

Important, to attach a Shadow DOM to an element, you can't write it directly into the HTML file. You'll need to define it using JavaScript:

let shadow_open   = document.getElementById('Wheel-1').attachShadow({ mode: 'open' }) // You'll be able to access the shadow Element.shadowRoot
let shadow_closed = document.getElementById('Wheel-N').attachShadow({ mode: 'closed' }) // You won't be able to access the shadow

Now attach the shadow element:

const branding = document.createElement('p')
branding.setAttribute('class', 'text')
branding.textContent = 'Pirelli'

const style = document.createElement('style')
style.textContent = '.text { color: red };'


The difference between using Shadow DOM elements, and changing the color brand from the CSS (using #Wheel-N) is the accessibilty. If you defined the Shadow DOM as closed, you won't be able to change the brand color using CSS (even if you used the !important attribute).

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.