Understanding Shadow DOM

Understanding Shadow DOM

Photo by Niels Kehl on Unsplash

Unleashing the Magic: Creating Custom Buttons with Shadow DOM

What is Shadow DOM?

Shadow DOM provides a way to attach a hidden separated DOM to an element.

Shadow DOM allows hidden DOM trees to be attached to elements in the regular DOM tree — this shadow DOM tree starts with a shadow root, underneath which you can attach any element, in the same way as the normal DOM.

It allows developers to encapsulate the styling and behavior of a web component within a private and isolated "shadow" realm. It enables the creation of custom elements with their unique designs and functionalities without affecting or being affected by the rest of the web page.

Let's break it down for a better understanding

Think of a web component like building your custom button. With shadow DOM, you create a private and exclusive space for the button's design and functionality, hidden from the rest of the page. This isolation ensures that your custom button behaves consistently and independently, regardless of its usage within the larger web page.

Let's explore a practical example of creating a custom button using shadow DOM.

In this example, we create a custom button using the CustomButton class, which extends the HTMLElement class. Inside the constructor, we create a shadow root using

this.attachShadow({ mode: 'open' })

And then, we add a regular button element to the shadow root, taking the text content from the <custom-button> tag. This way, the button's implementation is hidden within the shadow DOM, providing encapsulation and isolation.

By using the custom button <custom-button> in the HTML, you can interact with it just like any other button. The styles and functionality defined within the shadow DOM will not interfere with other parts of the page, ensuring a clean separation of concerns.

// JavaScript code for the custom component
class CustomButton extends HTMLElement {
  constructor() {
    super();

    // Create a shadow root
    this.attachShadow({ mode: 'open' });

    // Create a button element and add it to the shadow DOM
    this.button = document.createElement('button');
    this.button.textContent = this.textContent;
    this.shadowRoot.appendChild(this.button);

    // Attach a click event listener to the button
    this.button.addEventListener('click', () => {
      this.toggleColor();
    });
  }

  toggleColor() {
    // Toggle the background color between blue and green
    if (this.button.style.backgroundColor === 'blue') {
      this.button.style.backgroundColor = 'green';
    } else {
      this.button.style.backgroundColor = 'blue';
    }
  }
}

// Define the custom element
customElements.define('custom-button', CustomButton);

Now, use your custom button <custom-button> in the HTML just like any other standard HTML element:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Shadow DOM Custom Component</title>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <h1>Shadow DOM Custom Component Example</h1>
        <button>Native Button</button> 
        <custom-button>Custom button using shadow DOM</custom-button>
        <script src="script.js" type="module"></script>
    </body>
</html>
/* Global styles */
h1 {
  text-align: center;
}

/* Styles for the custom component */
custom-button {
  display: inline-block;
  padding: 10px 20px;
  background-color: #3498db;
  color: white;
  border: none;
  cursor: pointer;
  font-size: 16px;
}

This can be useful for a variety of purposes, such as:

  • Encapsulating CSS styles: Shadow DOM can be used to encapsulate CSS styles, which means that they will only be applied to the elements in the shadow DOM tree. This can be useful for preventing CSS conflicts between different components.
    In the context of the custom button example, shadow DOM allows us to encapsulate the CSS styles of our <custom-button> element. When we define the custom button element and create the shadow root, any CSS styles applied within the shadow DOM will only affect the elements inside that particular <custom-button> instance.

  • Hiding implementation details: Shadow DOM can be used to hide implementation details from the user. This separation enhances maintainability and reusability since developers can update or modify the internal implementation without affecting how users interact with the custom button.
    For instance, within the shadow DOM, we can add event listeners or other complex logic to handle button clicks or interactions. However, this implementation remains hidden within the shadow DOM, making the usage of the custom button straightforward for users.

  • Creating custom elements: Shadow DOM can be used to create custom elements, which are reusable components that can be used to build complex user interfaces.

Final Note

Shadow DOM is a powerful web technology that allows developers to build reusable and isolated web components. With its encapsulation and isolation capabilities, shadow DOM ensures that components work consistently across different parts of the page, making it an essential tool for modern web development. So go ahead, build your custom button, and experience the benefits of shadow DOM!

I hope you enjoyed reading this article. Please share it with your friends and colleagues. If you have any resources that can help you with the above points, please share them with me and everyone else in the comments. It will be beneficial!

Thank you so much! 😊


👉 Follow Me: LinkedIn Twitter GitHub