Creating a Material Design slider with Web Components. The Shadow DOM concept


As a developer dealing with the Front End technologies, you probably are familiar with attempts to reuse the code in the form of components, for example with libraries like React, Angular and Vue. Web Components implement a similar idea. It consists of a few technologies, that together create an environment suitable for creating reusable, encapsulated components. In this article, we go through the basics of Web Components stack. It consists of covering shadow DOM, custom elements, and templates by implementing a simple material design slider.

Custom elements

With custom elements, we can create new HTML tags, or extend existing ones. In this article, we create a material design slider. Let’s start by defining our new element. To do this, we extend the HTMLElement class and use the   function in the global   object.

Uncaught DOMException: Failed to execute ‘define’ on ‘CustomElementRegistry’: “slider” is not a valid custom element name

The above causes an error because the name of the component needs to have a dash. It helps to avoid name overlapping. It also allows the browser to tell the difference between custom elements and native ones. Let’s rename it and throw some functionality in:

Since we successfully registered a component, we can use it in our HTML. Every time we click on our slider, we see a message in the console. To make it visible, let’s add some styles to it too.

Using attributes

We can also use attributes with our web components. The most basic way would be to use them through the   function:

Basic custom element reactions

When using custom elements, we have access to a set of custom element reactions methods that run during its existence and act as lifecycle functions. For now, we take a look into three of them.

  • constructor – it runs when we create an instance of the element
  • connectedCallback – runs every time we insert the element into the DOM
  • disconnectedCallback – executes every time we remove the element from the DOM

We can use the above to improve our component.

As you can see, in the example above we use the  function to define a template of our custom element. Instead of doing that, we can use the Shadow DOM

Shadow DOM

A crucial thing about web components is encapsulation. It means isolating our components from the rest of the page in a similar manner to the  . Selectors and styles within the Shadow DOM node don’t reach outside of it, and we don’t have to worry about any conflicts.

To initialize the Shadow DOM, we use the attachShadow function.

The open mode means that the elements are accessible through JavaScript from outside

By the code above we create a shadow root. It is a start of a particular shadow DOM in a similar way that the   is the beginning of a regular DOM tree. Let’s inspect it in the Developer Tools.

Our Shadow tree root node is attached to the  , which we call a shadow host.

Styling shadow DOM

As you might have noticed, our styles no longer work. The above is because the styles from outside of the Shadow DOM are not applied to it. The most basic way to style the Shadow DOM is to add the   tag to it.

That does not seem too pleasant, though, and we would like to separate the style from the logic. Fortunately, according to W3C using   tags inside of a Shadow DOM is now a standard. Thanks to that, we can use the following syntax:

The only issue with that is the time when it starts fetching. It begins after the Shadow DOM has been initialized through our JavaScript. We can fix that by putting   in our HTML.

Now our additional style starts fetching right away, even though it does not apply to the whole document.

Native HTML tags with Shadow DOM

Some native HTML tags also implement Shadow DOM, but it is hidden from us by default. We can change this behavior for example, by setting   to true through about:config in Firefox.

Using templates

So far, so good! My main concern with the above is that defining the whole component through the   isn’t very pleasing. The contents of the   tag, are not rendered in the DOM, but can still be referenced through JavaScript. Thanks to that, we can use it to create a template that we can use in the shadow DOM.

We might come across an issue, though. The above is due to the fact that we need to look for the template after the DOM loads. To fix it, we use the load event of the window:

Running the cloneNode function with the “deep” flag set to true gives as a full clone of the template that we can use in our shadow DOM.

Putting everything together

After putting everything together, we have a very basic slider made with pure JavaScript and Web Components.





In this article, we’ve gone through the principles of Web Components. This included creating our HTML tags using custom elements, explaining the basics of the shadow DOM, and creating reusable HTML  templates. While there is much more to be said about the above technologies, this article serves as an introduction to Web Components. By learning them, we can both have another technology up to our sleeve and have a better understanding of how the browser works.

Notify of