Shadow DOM
Shadow DOM is a web standard that allows a component to encapsulate its own HTML structure, styles, and behavior — completely isolated from the main document. Styles defined inside a Shadow DOM do not leak out, and styles from the host page cannot leak in. It is the technology that makes truly portable, style-safe web widgets possible.
How Does Shadow DOM Work?
Shadow DOM creates an encapsulated subtree attached to a "shadow host" element in the main DOM. This subtree has its own scope for CSS selectors and JavaScript queries, meaning document.querySelector() from the parent page will not find elements inside the shadow tree. The boundary between the shadow tree and the main document is called the "shadow boundary."
To create a Shadow DOM, you call element.attachShadow({ mode: 'open' }) on a host element. The mode 'open' means external JavaScript can access the shadow root via element.shadowRoot, while 'closed' hides it. Inside the shadow root, you can use a <style> tag or CSSStyleSheet to define scoped styles that are completely isolated from the rest of the page.
Web Components — the broader standard that Shadow DOM is part of — also includes Custom Elements and HTML Templates. Together, they enable building reusable, encapsulated UI components that work natively in any browser without a framework dependency. Shadow DOM v1 is now supported in all modern browsers.
// Attaching a Shadow DOM to a host element
const host = document.getElementById('widget-host');
const shadow = host.attachShadow({ mode: 'open' });
// Add scoped styles — these won't affect the parent page
const style = document.createElement('style');
style.textContent = `
:host {
display: block;
font-family: system-ui, sans-serif;
}
.btn {
background: #7c3aed;
color: white;
padding: 8px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
}
`;
const btn = document.createElement('button');
btn.className = 'btn';
btn.textContent = 'Click Me';
shadow.appendChild(style);
shadow.appendChild(btn);Why Use Shadow DOM?
Why Shadow DOM is ideal for widgets: CSS encapsulation is the killer feature. When you ship a widget to thousands of different websites, you cannot predict what CSS frameworks, reset stylesheets, or specificity wars exist on those pages. Shadow DOM guarantees your widget looks exactly as designed, regardless of host page styles. It also prevents your widget's CSS from accidentally restyling the host page's elements.
Limitations to be aware of: Shadow DOM has a steeper learning curve than iFrames. Some CSS features like custom properties (CSS variables) can intentionally pierce the shadow boundary, which is useful for theming but requires careful design. Global CSS resets (e.g., `* { box-sizing: border-box }`) do not apply inside shadow trees, so you must explicitly set baseline styles. Additionally, some older analytics or A/B testing tools cannot query elements inside a closed Shadow DOM.
The WidgetJar Alternative
Every WidgetJar widget runs inside a Shadow DOM. This means your widget's styles are bulletproof — a host page with aggressive CSS resets, Bootstrap, or Tailwind will never break your widget's appearance. WidgetJar's renderer core builds on Shadow DOM to deliver pixel-perfect, isolated widgets that embed safely on any site.
Try WidgetJar Free →Related Terms
JavaScript Widget
A JavaScript widget is a self-contained, interactive UI component that is embedd…
iFrame
An iFrame (inline frame) is an HTML element that embeds another webpage inside t…
Embed Code
Embed code is a snippet of HTML, JavaScript, or a combination of both that you c…
CSS Selector
A CSS selector is a pattern used to target and style specific HTML elements on a…