Exploring CSS Shadow DOM and CSS Custom Shadow Parts
Source: Dev.to
Modern web development emphasizes building reusable, encapsulated components—a goal the Shadow DOM and CSS Custom Shadow Parts directly address. These browser features isolate component internals from the global page, avoiding style leakage and conflicts while still allowing controlled customization.
What is Shadow DOM?
Shadow DOM is a web standard that lets you create a separate, encapsulated DOM subtree for an element, known as a shadow tree. The subtree’s markup and styling are isolated from the main document DOM, preventing unintended interference. It’s the foundational technology behind Web Components.
Encapsulation
Internal structure and styles are hidden from the main document and external CSS.
Scoped Styles
Styles inside the shadow tree only affect its nodes; page styles cannot bleed in.
Shadow Host
The regular DOM element that hosts the shadow tree.
Shadow Root
The root node of the shadow tree, created via JavaScript with attachShadow().
const host = document.querySelector('#host');
const shadow = host.attachShadow({ mode: 'open' });
const span = document.createElement('span');
span.textContent = "I'm inside the shadow DOM!";
shadow.appendChild(span);
Without Shadow DOM, outer‑page styles can accidentally override a component’s internal styles (and vice‑versa), making large apps harder to maintain. Shadow DOM creates a “style and markup bubble” around components, ensuring predictable behavior regardless of the surrounding page.
Styling Inside Shadow DOM
Since styles are scoped inside the shadow root, you style shadow‑DOM elements internally with regular CSS placed inside the shadow tree.
shadow.innerHTML = `
span {
color: red;
border: 1px solid black;
}
Shadow DOM content
`;
This CSS applies only to elements inside the shadow tree, preventing conflicts with outside styles.
CSS Custom Shadow Parts
While Shadow DOM provides encapsulation, it also restricts customizing internal elements from outside. CSS Custom Shadow Parts let web components expose specific internal elements for external styling without breaking encapsulation.
/* External stylesheet */
my-component::part(button) {
background-color: green;
border-radius: 5px;
}
Example Component
class MyButton extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' }).innerHTML = `
button {
background-color: blue;
color: white;
padding: 10px;
border: none;
cursor: pointer;
}
Press me
`;
}
}
customElements.define('my-button', MyButton);
External styling
my-button::part(button) {
background-color: orange; /* Override internal button style */
}
The external CSS targets the inner button’s part="button" while the rest of the component remains encapsulated.
Key Features
| Feature | Description |
|---|---|
| Shadow DOM | Encapsulates markup and styles inside a shadow root, isolating from page styles. |
| Shadow Host | Regular DOM element that hosts the shadow root. |
| Scoped Styles | Styles inside the shadow root apply only within that tree. |
| CSS Custom Shadow Parts | Provides a sanctioned way for external styling of internal component parts. |
part attribute | Marks internal elements to be exposed for external styling. |
::part() selector | Targets parts from outside the shadow root for custom styling. |
Conclusion
By using Shadow DOM and CSS Custom Shadow Parts, developers can create robust, maintainable web components that are both encapsulated and customizable—ushering in a new era of reusable UI building blocks.