Element.attachShadow() is an instance method that attaches a Shadow DOM tree to a host element and returns a ShadowRoot. Learn open vs closed mode, custom elements, slots, and five try-it labs.
01
Kind
Instance method
02
Returns
ShadowRoot
03
Mode
open / closed
04
Host
Element + tree
05
Used for
Custom elements
06
Status
Baseline widely
Fundamentals
Introduction
Normal DOM children are part of the page’s main tree. A shadow tree is a separate DOM attached to a host element. Styles and markup inside the shadow root stay encapsulated—ideal for reusable components.
attachShadow() is the JavaScript way to create that root (you can also create one declaratively with the shadowrootmode attribute). It is the foundation of many custom elements.
💡
Beginner tip
Start with { mode: "open" }. Then you can read the tree later with element.shadowRoot.
Not every tag can host a shadow root (security / platform limits).
Calling again on an existing programmatic shadow root usually throws.
Optional flags: delegatesFocus, slotAssignment, clonable, serializable, and more.
Foundation
📝 Syntax
General form of Element.attachShadow (MDN):
JavaScript
attachShadow(options)
Parameters
options — an object that includes:
mode (required) — "open" (readable via element.shadowRoot) or "closed" (shadowRoot is null).
clonable (optional) — include the shadow root when cloning the host (default false).
delegatesFocus (optional) — focus the first focusable part when clicking non-focusable shadow content (default false).
slotAssignment (optional) — "named" (default, automatic slots) or "manual" (HTMLSlotElement.assign()).
serializable (optional) — allow serialization via getHTML() options (default false).
customElementRegistry (optional) — scoped registry for the shadow root.
referenceTarget (optional) — ID of an inner element that becomes the effective target of external references to the host.
Return value
Returns a ShadowRoot object.
Exceptions
MDN: may throw when attaching to an unsupported element, when shadow is disabled via custom element disabledFeatures, when a conflicting shadow root already exists, when declarative mode mismatches, or when an invalid customElementRegistry is passed.
Element.attachShadow() is Baseline Widely available (MDN: across browsers since January 2020). Logos use the shared browser-image-sprite.png sprite from this project. Newer options may vary.
✓ Baseline Widely available
Element.attachShadow()
Safe for production Shadow DOM and custom elements. Prefer open mode while learning.
BaselineWidely available
Google ChromeSupported · Desktop & Mobile
Yes
Microsoft EdgeSupported · Chromium
Yes
Mozilla FirefoxSupported · Desktop & Mobile
Yes
Apple SafariSupported · macOS & iOS
Yes
OperaSupported · Modern versions
Yes
Internet ExplorerNot supported
No
attachShadow()Excellent
Bottom line: Use attachShadow() to create encapsulated component trees. Start with mode: "open", then explore slots and closed mode as needed.
Wrap Up
Conclusion
Element.attachShadow() creates a ShadowRoot on a host element for encapsulated markup and styles. Use open mode for easy access via shadowRoot, and explore slots when building flexible custom elements.
Attach once per host in the custom element constructor
Keep closed-mode roots in a private field if you need them
Use slots for light DOM composition
Scope component CSS inside the shadow tree
❌ Don’t
Call attachShadow() twice on the same programmatic host
Assume every HTML tag can host a shadow root
Expect element.shadowRoot to work in closed mode
Leak global styles that break component encapsulation unintentionally
Forget newer options may need capability checks
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about Element.attachShadow()
Create an encapsulated ShadowRoot on a host element.
5
Core concepts
📝01
Returns
ShadowRoot
API
🔒02
Mode
open / closed
Access
🧩03
Used in
custom elements
Components
✅04
Baseline
widely available
Status
⚡05
Slots
named / manual
Compose
❓ Frequently Asked Questions
It attaches a shadow DOM tree to an element (the shadow host) and returns a ShadowRoot. You then append markup and styles inside that root for encapsulation.
No. MDN marks Element.attachShadow() as Baseline Widely available (across browsers since January 2020). It is not Deprecated, Experimental, or Non-standard. Some newer options may have narrower support.
With mode: "open", element.shadowRoot returns the ShadowRoot. With mode: "closed", element.shadowRoot is null — keep the return value from attachShadow() if you still need access from your own code.
No. Only certain elements can (for example div, span, section, and custom elements). Some elements cannot for security reasons. Attaching to an unsupported element throws.
Calling attachShadow() again usually throws. A special case is a matching declarative shadow root: the existing ShadowRoot can be cleared and returned when modes match.
For open mode use host.shadowRoot. For closed mode use the ShadowRoot reference you saved from attachShadow().
Did you know?
You can also create a shadow root declaratively with a <template shadowrootmode="open"> (or closed). Client code can still call attachShadow() when modes match to take over a server-rendered declarative root.