Skip to main content Skip to footer

Using Shadow DOM (How to Build Your Own Shadow Elements)

Shadow DOM

Shadow DOM may have a name that conjures images of a dark world. But it’s actually an interesting feature of modern browsers—allowing for easy encapsulation of DOM elements and smart web components. If you‘re a front-end developer, you’ll likely benefit from understanding how Shadow DOM works and what it can do for you.

What Is Shadow DOM, and How Do You Use It?

The easiest way to explain what Shadow DOM does is to demonstrate an example of Shadow DOM in action.

A Quick Example of Shadow DOM

The easiest way to explain what Shadow DOM does is to demonstrate an example of Shadow DOM in action.

Let's take a look at a range input type, a DOM element that requires its own DOM subtree for proper rendering (something that can differ wildly between browsers):

<input type="range" />

That seems like a simple enough element. But what makes the data input type interesting is that, when rendered, it appears like a slider instead of a standard text input — despite the fact that a slider doesn't appear anywhere in the main document's DOM:

This sub-element, with no apparent DOM associated with it in the browser inspector or via JavaScript, is the Shadow DOM. It’s a DOM subtree that we can't access via conventional means in order to better encapsulate complex functionality not typically associated with traditional HTML pages.

One interesting thing to note is that, while JavaScript events are retargeted to the parent element in order to avoid exposing access to the internal Shadow DOM elements, these same elements can be interacted with using CSS as long as you know what the elements are and how to access them.

But, as cool as it is, how can we best utilize the Shadow DOM in our own projects?

Shadow DOM: Talking the Talk

Before we can build our own Shadow DOM element, we must first learn to speak the language. At its core, each Shadow DOM element is composed of three parts: a host, a tree, a boundary, and a root.

Shadow Host

The Shadow Host is the DOM node that the Shadow DOM element is attached to. In the case of our slider above, this would be the input tag.

Shadow Tree

The Shadow Tree is the entire DOM tree inside the Shadow DOM. Looking back to our slider, this would be everything that makes up the track and icon.

Shadow Boundary

The Shadow Boundary is the place where the Shadow DOM ends, and the main document DOM begins [insert Lion King reference here].

Shadow Root

And finally, the Shadow Root. This element is the root node of the Shadow Tree.

Building Your Own Shadow Elements

Building your own shadow elements is a surprisingly straightforward task in standard JavaScript. All it takes to attach a Shadow DOM to an element is to call the attachShadow() method on that element, and then building and attaching the internal elements as you would any other DOM element:

let shadow = document.findElementById("host").attachShadow({mode: 'open'});
var paragraph = document.createElement("p");


It is important to point out that the attachShadow() method accepts an options object as its only parameter, and that object contains only one potential option: mode. The mode option specifies whether or not the shadow element can be accessed from the JavaScript written to the main document. While it may be tempting to use a closed mode, generally speaking, it is much more hassle than it's worth to deal with a closed shadow element when an open element still provides the encapsulation benefit that comes with the Shadow DOM.

Why Build Your Own Shadow Elements?

Because none of the code inside a Shadow DOM element can affect anything outside of it, the Shadow DOM is an excellent tool for encapsulation. In some circumstances, obscuring elements may be used as well; however, this method is hardly fool proof, so you are better off reaping the benefits of the encapsulation and management features instead.

While the Shadow DOM operates… in the shadows… it is hardly a rare thing. It is commonly used in other HTML5 elements to encapsulate targeted functionality for a better developer experience (such as audio and video players), and well-documented elements provide mechanisms for manipulation where appropriate, allowing for a little light to be cast on the Shadow DOM.

Empower your development. Build better applications.

Try GrapeCity's Tools for JavaScript and .NET

Zachary Flower

comments powered by Disqus