Skip to main content

What is the Shadow DOM?

Answer

Shadow DOM is a web standard that provides encapsulation for DOM and CSS. It allows you to attach a hidden, separate DOM tree to an element, keeping its internal structure and styles isolated from the main document.

DOM Structure

Creating Shadow DOM

// Get the host element
const host = document.querySelector("#my-component");

// Attach shadow root
const shadow = host.attachShadow({ mode: "open" });

// Add content to shadow DOM
shadow.innerHTML = `
<style>
/* These styles are scoped! */
p { color: blue; font-size: 20px; }
.internal { background: yellow; }
</style>
<div class="internal">
<p>This is inside Shadow DOM</p>
</div>
`;

Mode: Open vs Closed

// Open mode - shadow root accessible via JavaScript
const openShadow = element.attachShadow({ mode: "open" });
console.log(element.shadowRoot); // Returns shadow root

// Closed mode - shadow root not accessible
const closedShadow = element.attachShadow({ mode: "closed" });
console.log(element.shadowRoot); // Returns null

CSS Encapsulation

<!-- Main document -->
<style>
p {
color: red;
} /* Won't affect shadow DOM */
.internal {
background: green;
} /* Won't affect shadow DOM */
</style>

<div id="my-component">
<!-- Shadow DOM content is protected -->
</div>

<p>This is red (main document)</p>
// Inside shadow DOM
shadow.innerHTML = `
<style>
p { color: blue; } /* Only affects this shadow DOM */
</style>
<p>This is blue (shadow DOM)</p>
`;

Slots - Content Projection

// Component with slot
shadow.innerHTML = `
<style>
.wrapper { border: 2px solid blue; padding: 10px; }
</style>
<div class="wrapper">
<slot></slot> <!-- Content goes here -->
</div>
`;
<!-- Usage -->
<my-component>
<p>This content goes into the slot!</p>
</my-component>

Named Slots

shadow.innerHTML = `
<header>
<slot name="title"></slot>
</header>
<main>
<slot></slot> <!-- Default slot -->
</main>
<footer>
<slot name="footer"></slot>
</footer>
`;
<my-component>
<h1 slot="title">Card Title</h1>
<p>Main content (default slot)</p>
<span slot="footer">Footer text</span>
</my-component>

Real-World Examples

Shadow DOM is used in native HTML elements:

<!-- These use Shadow DOM internally -->
<video controls></video>
<input type="range" />
<input type="date" />
<details>
<summary>Click</summary>
Content
</details>

Browser DevTools

To inspect Shadow DOM:

  1. Open DevTools → Elements
  2. Click ⚙️ Settings → Show user agent shadow DOM
  3. Expand #shadow-root in the element tree

Key Points

  • Encapsulation: Styles and DOM are isolated
  • Scoped CSS: No style leaking in or out
  • Slots: Allow content projection
  • Native support: Used by browser UI elements
  • Web Components: Foundation for custom elements