Shadow DOM

It gives component internals an isolated DOM and style boundary.

···
html
<div class="v"><header>STYLE BOUNDARY <span id="outerLabel">outer: blue</span></header><div class="stage shadow"><div class="outer" id="outer">document style<template id="tpl"><div class="inner">shadow card</div></template><div id="host"></div></div></div><div class="muted">outer selector stops at shadow root</div></div>
css
.v{width:min(94vw,760px);height:min(88vh,320px);padding:clamp(9px,2.4vmin,18px);border:1px solid var(--line);border-radius:12px;background:var(--surface);font:500 clamp(12px,2.4vmin,16px)/1.3 var(--font-sans,system-ui,sans-serif);display:flex;flex-direction:column;gap:clamp(5px,1.4vmin,10px);overflow:hidden}.v header{display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--accent);font-weight:700}.v header span{color:var(--muted);font-weight:500}.v .stage{flex:1;min-height:0;position:relative}.v .muted{color:var(--muted)}.v .active{background:color-mix(in srgb,var(--accent) 18%,var(--surface));border-color:var(--accent)!important;color:var(--fg)}.v button{font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:7px;padding:5px 8px;cursor:pointer}.shadow{display:grid;place-items:center}.outer{width:70%;min-height:75%;padding:9px;border:2px dashed var(--accent-2);border-radius:9px;color:var(--accent-2);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:7px;transition:color .5s,border-color .5s}.outer.hot{color:var(--accent-3);border-color:var(--accent-3)}#host{width:65%;display:block}
js
const host=document.getElementById("host");host.attachShadow({mode:"open"}).innerHTML="<style>.inner{padding:8px;text-align:center;color:white;background:#0e9f6e;border-radius:7px;font:600 13px system-ui}</style><div class=inner>shadow card</div>";let hot=false;function tick(){hot=!hot;document.getElementById("outer").classList.toggle("hot",hot);document.getElementById("outerLabel").textContent=hot?"outer: amber":"outer: blue"}tick();setInterval(tick,1100)

Shadow DOM attaches a separate tree beneath a host element. Ordinary document selectors do not reach straight into it, and component styles stay inside.

The demo changes the outer CSS color while the inner card keeps its color. If consumers need styling control, expose custom properties or `::part` intentionally.

When to use

Use it to encapsulate reusable web components and reduce style collisions.

Open as page ↗