About Shadow DOM & shadowRoot
⭐ Shadow DOM & shadowRoot in JavaScript – The Complete Beginner-to-Advanced Guide
If you’ve ever built complex UIs, you’ve probably faced these problems:
- Styles bleeding into other components
- CSS conflicts across pages
- Script interference
- Hard-to-maintain UI modules
What if you could create your own private DOM—a protected area where:
- Your CSS NEVER leaks outside
- Outside CSS NEVER affects it
- Your DOM structure is hidden
- Everything inside remains completely self-contained
Welcome to the Shadow DOM.
At the center of it all is the shadowRoot.
🔶 1. What Exactly Is the Shadow DOM?
The Shadow DOM is a hidden, encapsulated DOM tree attached to an element, separated from the main document DOM.
It is used mainly in Web Components to create custom, reusable HTML elements with private DOM and styles.
Think of it as:
A mini-webpage inside an element — with its own HTML, CSS, and JS — isolated from the outside world.
🔶 2. What Is shadowRoot?
The shadowRoot is the root node of the shadow DOM.
It represents the entry point into this private DOM.
You create a shadowRoot using:
element.attachShadow({ mode: "open" });
And this shadowRoot becomes the container for your private DOM nodes.
🔶 3. Why Do We Need shadowRoot?
Because it gives you:
✔ Encapsulation
No CSS conflicts. No script interference.
✔ Style Isolation
Your component looks the same everywhere.
✔ DOM Privacy
Outside JS cannot access inner DOM (if mode: 'closed').
✔ Reusability
Build design systems, UI libraries, components.
🔶 4. Creating a shadowRoot (Step-by-Step)
Example:
<div id="box"></div>
<script>
const box = document.querySelector("#box");
const shadow = box.attachShadow({ mode: "open" });
shadow.innerHTML = `
<style>
p { color: red; font-size: 20px; }
</style>
<p>Hello from Shadow DOM!</p>
`;
</script>
Result:
<p>inside the shadow DOM appears red- If the main document has styles like
p { color: blue; }, it will NOT affect this paragraph.
🔶 5. mode: "open" vs mode: "closed"
| Mode | Meaning | Can access via element.shadowRoot? | | ---------- | ---------------------------------- | ---------------------------------- | | open | Shadow root is accessible publicly | ✔ Yes | | closed | Shadow root is hidden from outside | ❌ No |
Example of closed shadow DOM:
element.attachShadow({ mode: "closed" });
Trying to access:
console.log(element.shadowRoot); // null
Used for high-security components where internal structure must be hidden.
🔶 6. Adding Elements Inside shadowRoot
Append elements like normal DOM
const shadow = element.attachShadow({ mode: "open" });
let btn = document.createElement("button");
btn.textContent = "Click Me";
shadow.append(btn);
🔶 7. Styling Inside the Shadow DOM
Shadow DOM protects styles in both directions.
Example:
shadow.innerHTML = `
<style>
button {
background: black;
color: white;
}
</style>
<button>Shadow Button</button>
`;
Outside CSS like:
button {
background: yellow;
}
Will NOT change the shadow DOM button.
🔶 8. Host Selector – Styling the Host Element
Sometimes you want to style the custom element itself, not its internal nodes.
Use:
:host {
display: block;
padding: 10px;
border: 2px solid black;
}
🔶 9. :host-context() – Styling Based on Outer DOM
Example:
:host-context(.dark-theme) {
background: black;
color: white;
}
The shadow element reacts to parent page conditions without exposing itself.
🔶 10. Slotting Content into Shadow DOM
Shadow DOM gives a private DOM, but you may want to allow user content.
Use <slot>:
shadow.innerHTML = `
<style>
::slotted(span) {
color: green;
}
</style>
<div>
<slot></slot>
</div>
`;
HTML outside:
<my-card>
<span>User Content</span>
</my-card>
Slot displays user content inside the shadow DOM without breaking encapsulation.
🔶 11. Full Example – Creating a Custom Component Using shadowRoot
Step 1: Define custom element
class MyBox extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
shadow.innerHTML = `
<style>
div {
padding: 20px;
background: lightblue;
font-size: 18px;
}
</style>
<div>
<slot></slot>
</div>
`;
}
}
customElements.define("my-box", MyBox);
Step 2: Use it in HTML
<my-box>Hello, I am inside a shadow DOM!</my-box>
🔶 12. Accessing shadowRoot (open shadow DOM)
const el = document.querySelector("my-box");
console.log(el.shadowRoot); // ShadowRoot object
🔶 13. Why You Should Not Overuse Closed Shadow DOM
- Hard to debug
- Not accessible to developers
- Conflicts with dev tools
- Not recommended unless necessary
Most modern component libraries use open mode.
🔶 14. Shadow DOM Event Behavior
Inside the shadow DOM, events still bubble up but with protection.
If a button inside the shadow DOM is clicked:
- The event bubbles outward
- But the DOM path is rewritten to hide private nodes
- Outside code cannot see the internal DOM structure
Example:
button.addEventListener("click", (e) => console.log(e.composedPath()));
Shadow-internal nodes may appear only when composed: true is allowed.
🔶 15. Shadow DOM vs Regular DOM
| Feature | Regular DOM | Shadow DOM | | ---------------- | ----------- | --------------- | | Style isolation | ❌ No | ✔ Yes | | Script isolation | ❌ No | ✔ Partial | | Encapsulation | ❌ None | ✔ Strong | | Reusability | Average | Excellent | | Used in | All HTML | Custom elements |
🔶 16. Real World Uses of Shadow DOM
You rely on shadow DOM every day in modern web dev:
<video>element UI<input>styling- Browsers' custom widgets
- Web components (frameworks like Lit, Stencil, Shoelace)
- Design systems
- Component libraries
Shadow DOM powers most of the modern “component-style architecture”.
⭐ Final Summary
shadowRoot is the root of a shadow DOM:
A private, isolated DOM attached to an element.
With a shadow root, you get:
✔ Encapsulation ✔ Private CSS ✔ Private DOM ✔ DOM separation ✔ No CSS bleeding ✔ No conflicts ✔ Support for slots ✔ Custom components
Shadow DOM is the foundation of modern Web Components, making them maintainable, scalable, and conflict-free.
If you'd like next:
- Topic: closed vs open shadow DOM
- Topic: lifecycle callbacks in Web Components
- Topic: slots vs templates
- Topic: styling strategies for web components
Tell me the next topic!
Comments
Post a Comment