What on earth is the shadow DOM and why it matters

We’ve all heard of the DOM at some point. It’s a topic that is quickly brushed over and not enough discussion around it. The name shadow DOM sounds somewhat sinister — but trust me, it’s not.

The concept of DOMs is one of the foundations of the web, interfaces and deeply intertwined with JavaScript.

Many know what a DOM is — but not at the same time. For starters, it stands for Document Object Model — but what does that mean? Why is it important? and how is understanding how it works relevant to your next coding project?

Read on to find out.

What exactly is a DOM?

There’s a misconception that HTML elements and DOM are one of the same. However, they are separate and different in terms of functionality and how they are created.

HTML is a markup language. Its sole purpose is to dress up content for rendering. It uses tags to define elements and uses words that are human-readable. It is a standardized markup language with a set of predefined tags. 

Markup languages are different from typical programming syntaxes because they don’t do anything other than create demarcations for content. 

The DOM, however, is a constructed tree of Objects that are created by the browser or rendering interface. In essence, it acts sort of like an API for things to hook into the markup structure.

So what does this tree look like?

Let’s take a quick look at the HTML below:

<!doctype html>
<h1>Welcome to the site!</h1>
<p>How, now, brown, cow</p>

This will result in the following DOM tree.

Since all elements and any styling in an HTML document exists on the global scope, it also means that the DOM is one big globally scoped object. 

document in JavaScript refers to the global space of a document. The querySelector() method lets you find and access a particular element type, regardless of how deeply nested it sits in the DOM tree, provided that you have the pathway to it correct.

For example –


This will select the first element in the document with class="heading"

So if you do something like this — 


This will target the first <p> element that exists in a document. 

To be more specific, you can also do something like this — 


This will target the first instance of <h1 class="heading">

Using .innerHTML = "" will give you the ability to modify whatever sits in between the tags. So, for example, you can do something like this –

document.querySelector("h1").innerHTML = "Moooo!"

This will change the content inside the first <h1> tags to Moooo!

Now that we have the basics of DOMs sorted, let’s talk about when DOM starts to exist with a DOM. 

DOM within DOMs — aka shadow DOMs

There are times when a straight single object DOM will suffice all the requirements of your web app or webpage. Sometimes, you need 3rd party scripts to display things without it messing with your pre-existing elements.

This is where shadow DOMs come into play. 

Shadow DOMs are DOMs that sits in isolation and has its own set of scopes and isn’t part of the original DOM. 

Shadow DOMs are essentially self-contained web components, making it possible to build modular interfaces without it clashing with one another.

Browsers automatically attach shadow DOMs to some elements such as <input> , <textarea> and, <video>

But sometimes you need to manually create the shadow DOM in order to extract out the parts you need. In order to do this, you need to first create a shadow host, followed by a shadow root.

Setting up the shadow host

In order to split out a shadow DOM, you need to figure out which set of wrappers you want to extract out.

For example, you want the host class to be the set of wrappers that defines the boundaries of your shadow DOM.

<!doctype html>
<h1>Welcome to the site!</h1>
<p>How, now, brown, cow</p>
<span class="host">
<span class="host">

Under normal circumstances, span isn’t automatically converted into a shadow DOM by the browser. To do this via JavaScript, you need to use querySelector() and attachShadow() methods.

const shadowHost = document.querySelector(".host");
const shadow = shadowHost.attachShadow({mode: 'open'});

shadow is set up to be the shadow root of our shadow DOM. The elements then become a child of an extracted and separate DOM with .host as the root class element.

While you can still see the HTML in your inspector, the host portion of the code is no longer visible to the root code. 

In order to access this new shadow DOM, you just need to use a reference to the shadow root — i.e. shadow in the example above. 

For example, you want to add some content. You can do so with something like this — 

const paragraph = document.createElement("p");
paragraph.text = shadow.querySelector("p");
paragraph.innerHTML = "helloooo!";

This will create a new p element inside your shadow root with the text helloooo!

Parts of a shadow DOM

The parts of a shadow DOM consists of four parts — the shadow host, the shadow tree, the shadow boundary, and the shadow root.

The shadow host is the regular DOM node that the shadow DOM is attached to. In the examples previously, this is through the class host

The shadow tree looks and acts like a normal DOM tree, except its scope is limited to the edges of the shadow host.

The shadow boundary is the place where the shadow DOM starts and ends.

And finally, the shadow root is the root node of the shadow tree. This is different from the shadow host (i.e. host class based on the examples above). 

If we look at this code again — 

const shadowHost = document.querySelector(".host");
const shadow = shadowHost.attachShadow({mode: 'open'});

The shadowHost constant is our shadow host, while shadow is actually the shadow root. The difference between these two is that shadow returns a DocumentFragment while the shadowHost returns a document element. 

Think of the host as a placeholder for the location of where your actual shadow DOM will be.

Why do shadow DOMs matter?

Now comes the big question — why do shadow DOMs matter?

Shadow DOM is a browser technology that’s used to scope variables and CSS in web components.

For starters, a DOM is an object and you can’t possibly do all you need to do with a single object without it stepping over boundaries we want to certainly keep separate.

This means that shadow DOMs allow for encapsulation — that is, the ability to keep markup structure, style, and behavior separated and hidden from other code so they don’t clash.

And that’s the basics of shadow DOMs. 



About Author /

I code. I write. I hustle. Living the #devLife remotely. Subscribe to my newsletter to stay connected with my latest posts and dev thoughts. Want to collaborate? DM me on LinkedIn

Leave a Comment

Your email address will not be published.

Start typing and press Enter to search