Heading image for post: Basics of Shadow DOM

Basics of Shadow DOM

Profile picture of Craig Hafer

Table of Contents

  • What is the Shadow DOM?
  • 4 Main Parts
  • How it is created
  • Style Isolation
  • JS Isolation
  • Conclusion
  • If you work in the world of web, there's no doubt you've run into the Shadow DOM in one form or another. Even if it was hiding in the shadows and you didn't even know it was there. In this blog post I want to go over the basics of the Shadow DOM so that you can have a better understanding of what's really going on, should you ever notice one in "the wild".

    Well, to start off, what even IS a Shadow DOM? Is it the DOM's shady twin brother, or perhaps some kind of alternate-evil version? For me, my mind goes right to Shadow Link from the Legend of Zelda: Ocarina of Time.

    However, there is no need to fear the Shadow DOM. It actually a very helpful tool that allows complex elements to be isolated and abstracted.

    What is the Shadow DOM

    The Shadow DOM is an isolated and scoped DOM subtree within a web component

    Basically, the Shadow DOM is an entirely separate DOM tree that branches off of an element. This separate DOM tree is completely isolated, allowing it to be protected from CSS and Javascript

    4 Main parts of the Shadow DOM

    Before we dive in to constructing Shadow DOMs, let's cover the basics of the 4 different parts.

    Shadow Host
    The shadow host is the element that the Shadow DOM is attached to

    Shadow Tree
    The shadow tree is the entirely separate structure the makes up the Shadow DOM

    Shadow Root
    The shadow root is the root node of the shadow tree that is connected to the shadow host

    Shadow Boundary
    The shadow boundary is the line the separates the Shadow DOM from the rest of the main DOM

    Here is a good visual representation of this found in the mdn web docs.

    image

    So, how are Shadow DOMs created?

    Any HTML element can have a Shadow DOM attached to it. This is typically done when creating a custom HTML element. This is done by using Element.attachShadow()

    Note: attachShadow() takes an option of mode which can be either "open" or "closed"

    You manipulate the Shadow DOM using Javascript exactly the same way you would the regular DOM.

    Given the following HTML:

    <html>
      <body>
        <p>This is not part of the Shadow DOM</p>
    
        <div id="host"> 
        </div>
      </body>
    </html>
    

    You could do the following:

    // Attach an open Shadow DOM to a host
    const host = document.querySelector("#host");
    const shadow = host.attachShadow({ mode: "open" });
    
    // Create a p element and give it some text
    const p = document.createElement("p");
    p.textContent = "This is part of the Shadow DOM"
    
    // Append the newly created element to the Shadow DOM
    shadow.appendChild(p);
    

    This would then turn our HTML into this:

    <html>
      <body>
        <p>This is not part of the Shadow DOM</p>
        <div id="host"> 
          #shadow-root (open)
            <p>This is part of the Shadow DOM</p>
        </div>
      </body>
    </html>
    

    image

    Isolation of styles

    So now that we see how a simple Shadow DOM is created, let's look at some of the benefits of isolation this gives us.

    Remember, everything inside of the Shadow DOM is completely separate. So it will not receive any styles or javascript changes on the page.

    I'll show a quick example using styles. Let's add the following styles to our page:

    p {
      background: #ae1f23;
      border-radius: 5px;
      border: solid black 1px;
      box-shadow: 4px 4px 4px rgba(0, 0, 0, 0.2);
      color: white;
      padding: 4px;
      width: fit-content;
    }
    

    image

    As you can see, our Shadow DOM is completely untouched! And the inverse would be true too. We could've just as easily thrown special styles onto our Shadow DOM that would be isolated from the rest of the web page's styling.

    Encapsulation of Javascript

    image

    As you can see here, using `document.querySelectorAll("p") to grab all the <p> elements, only gives us an array with one <p> tag. That's because the Shadow DOM is completely isolated and skipped over.

    Now, that's not to say that we can't use any Javascript to manipulate our Shadow DOM.

    image

    Here we can take our host and call shadowRoot to then do whatever we might need to with it.
    However, if the shadow-root was given a {mode: "closed"}, we would not be able to access it through Javascript.
    We can see that here shadowRoot returns null:

    image

    Conclusion

    So, as you can see there isn't too much that goes in to what makes up the Shadow DOM. It's an interesting tool that is useful when creating custom HTML elements. The isolation makes it nice so that we can protect it from other styles and scripts on the page.

    Just in case you think you're somebody who's never come across a Shadow DOM, did you know that there are plenty of HTML elements that utilize the Shadow DOM under the hood? They use a more technical built-in Shadow DOM, so it isn't as inspectable as this one, but elements like <video>, <input type="range">, <progress>, and more all use built-in Shadow DOMs to abstract their complex parts into a simple element.

    I hope you were able to learn something new and make sure you keep your eyes peeled for Shadow DOMs as you develop.

    If you want to learn more about this, I highly suggest reading the mdn web docs as they cover a lot more than this post.


    Photo by Rene Böhmer on Unsplash

    More posts about html

    • Adobe logo
    • Barnes and noble logo
    • Aetna logo
    • Vanderbilt university logo
    • Ericsson logo

    We're proud to have launched hundreds of products for clients such as LensRentals.com, Engine Yard, Verisign, ParkWhiz, and Regions Bank, to name a few.

    Let's talk about your project