Shadow DOM

What is the Shadow DOM?

Before diving into what shadow DOM is, let us revise the actual DOM. DOM (Document Object Model) is a programming interface for web documents. It is an interface for programs, just as we have a user interface for the users to interact with. It allows programs to manipulate the structure, style, and content of web documents dynamically. The DOM is what you see when you inspect a webpage in the browser’s developer tools.

A typical DOM Figure 1. An example of what a DOM looks like

The Shadow DOM on the other hand is a web standard that allows you to attach a hidden, separate DOM to an element. It’s like a small, self-contained document fragment that is attached to a “host” element but operates independently of the main document’s DOM. This isolation enables the creation of reusable components without fear of styling conflicts or JavaScript clashes.

Shadow DOM is an essential part of Web Components that enables encapsulation of your component’s structure, style, and behavior. This encapsulation means that the component’s internal implementation details (like its DOM subtree and styling) are hidden from the rest of the application, preventing styles from leaking in or out and JavaScript from accidentally manipulating the internal state.

Key Concepts

  • Encapsulation: The Shadow DOM provides a way to encapsulate a component’s DOM and styles, preventing them from affecting the rest of the document.
  • Shadow Root: The root of the shadow DOM tree, attached to an element in the regular DOM.
  • Shadow Boundary: The boundary that separates the shadow DOM from the regular DOM, ensuring isolation of styles and scripts.
  • Scoped Styles: Styles defined within the shadow DOM are scoped to the shadow tree and do not affect the main document.

Creating Shadow Roots

To use the Shadow DOM in a custom element, you first need to attach a shadow root to the element using the attachShadow() method. This method is called on the custom element and takes a configuration object with a mode property, which can be set to "open" or "closed".

  • Open: The shadow DOM can be accessed from JavaScript outside the shadow root using the element.shadowRoot property.
  • Closed: The shadow DOM cannot be accessed from the outside, providing stronger encapsulation.

Create a file called my-shadowed-element.js in the root of your project and add the following code

javascript
	class MyShadowedElement extends HTMLElement {
	  constructor() {
	    super();
	    // Attach a shadow root to the element.
	    this.attachShadow({ mode: 'open' });
	  }
	}

Adding Content to the Shadow DOM

Once a shadow root has been attached, you can add content to the Shadow DOM just like you would to the regular DOM. However, instead of directly manipulating this.innerHTML, you’ll work with this.shadowRoot.innerHTML.

Update my-shadowed-element.js to add a styled <p> element to the shadow root:

javascript
	class MyShadowedElement extends HTMLElement {
	  constructor() {
	    super();
	    this.attachShadow({ mode: 'open' });
	    this.shadowRoot.innerHTML = `
	      <style>
	        p { color: blue; }
	      <\/style>
	      <p>Hello, Shadow DOM!</p>
	    `;
	  }
	}
	
	customElements.define('my-shadowed-element', MyShadowedElement);

Add the Custom Element to the HTML

Add the following to your index.html file to use the my-shadowed-element custom element:

html
	<!DOCTYPE html>
	<html lang="en">
	  <head>
	    <meta charset="UTF-8" />
	    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
	    <title>Web Components Introduction</title>
	    <script src="my-greeting.js" defer></script>
	    <script src="my-shadowed-element.js" defer></script>
	  </head>
	  <body>
	    <my-greeting></my-greeting>
	    <my-shadowed-element></my-shadowed-element>
	  </body>
	</html>

The output should display a blue “Hello, Shadow DOM!” message on the page:

Shadow Root Figure 1. An example of what a shadow dom looks like

Encapsulation in Action

The encapsulation provided by the Shadow DOM ensures that the styling and scripting inside your component do not interfere with the rest of the document or vice versa. For instance, the p { color: blue; } style in the example above only applies to <p> elements inside my-shadowed-element, not to any <p> elements outside it.

Conclusion

The Shadow DOM is a powerful feature of Web Components that provides the means to encapsulate and isolate a component’s structure, style, and behavior. By leveraging the Shadow DOM, developers can create more robust, reusable, and maintainable components that coexist peacefully in complex web applications without fear of unexpected interactions.

This lesson covered the basics of creating and using a shadow root to add encapsulation to your custom elements. As you continue to explore Web Components, you’ll find the Shadow DOM to be an invaluable tool in your development arsenal.

Reference