Element: attachShadow() method

Baseline Widely available *

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

* Some parts of this feature may have varying levels of support.

The Element.attachShadow() method attaches a shadow DOM tree to the specified element and returns a reference to its ShadowRoot.

Elements you can attach a shadow to

Note that you can't attach a shadow root to every type of element. There are some that can't have a shadow DOM for security reasons (for example <a>).

The following is a list of elements you can attach a shadow root to:

Calling this method on an element that is already a shadow host

The method may be called on an element that already has a declarative shadow root, provided the specified mode mode matches the existing mode. In this case the ShadowRoot that was already present will be cleared and returned. This allows for cases where, for example, server-side rendering has already declaratively created a shadow root, and then client-side code attempts to attach the root again.

Otherwise calling attachShadow() on an element that already has a shadow root will throw an exception.

Syntax

js
attachShadow(options)

Parameters

options

An object which contains the following fields:

mode

A string specifying the encapsulation mode for the shadow DOM tree. This can be one of:

open

Elements of the shadow root are accessible from JavaScript outside the root, for example using Element.shadowRoot:

js
element.attachShadow({ mode: "open" });
element.shadowRoot; // Returns a ShadowRoot obj
closed

Denies access to the node(s) of a closed shadow root from JavaScript outside it:

js
element.attachShadow({ mode: "closed" });
element.shadowRoot; // Returns null
clonable Optional

A boolean that specifies whether the shadow root is clonable: when set to true, the shadow host cloned with Node.cloneNode() or Document.importNode() will include shadow root in the copy. Its default value is false.

customElementRegistry Optional

A CustomElementRegistry that will be used as the scoped custom element registry of the attached shadow root. If null or undefined, the shadow root will use the global registry referenced by Window.customElements.

delegatesFocus Optional

A boolean that, when set to true, specifies behavior that mitigates custom element issues around focusability. When a non-focusable part of the shadow DOM is clicked, the first focusable part is given focus, and the shadow host is given any available :focus styling. Its default value is false.

referenceTarget Optional

A string value that indicates the effective target of any element reference made against the shadow host from outside the host element. The value should be the ID of an element inside the shadow DOM. If set, target references to the host element from outside the shadow DOM will cause the referenced target element to become the effective target of the reference to the host element.

serializable Optional

A boolean that, when set to true, indicates that the shadow root is serializable. If set, the shadow root may be serialized by calling the Element.getHTML() or ShadowRoot.getHTML() methods with the options.serializableShadowRoots parameter set true. Its default value is false.

slotAssignment Optional

A string specifying the slot assignment mode for the shadow DOM tree. This can be one of:

named

Elements are automatically assigned to <slot> elements within this shadow root. Any descendants of the host with a slot attribute which matches the name attribute of a <slot> within this shadow root will be assigned to that slot. Any top-level children of the host with no slot attribute will be assigned to a <slot> with no name attribute (the "default slot") if one is present.

manual

Elements are not automatically assigned to <slot> elements. Instead, they must be manually assigned with HTMLSlotElement.assign(). Its default value is named.

Return value

Returns a ShadowRoot object.

Exceptions

NotSupportedError DOMException

This error may be thrown when you try to attach a shadow root to an element:

  • outside the HTML namespace or that can't have a shadow attached to it.
  • where the element definition static property disabledFeatures has been given a value of "shadow".
  • that already has a shadow root that was not created declaratively.
  • that has a declarative shadow root but the specified mode does not match the existing mode.
  • while passing a customElementRegistry value that isn't null or a locally scoped registry (that you created using new CustomElementRegistry()). The error would be thrown if you passed the global registry.

Examples

Word count custom element

The following example is taken from our word-count-web-component demo (see it live also). You can see that we use attachShadow() in the middle of the code to create a shadow root, which we then attach our custom element's contents to.

js
// Create a class for the element
class WordCount extends HTMLParagraphElement {
  constructor() {
    // Always call super first in constructor
    super();

    // count words in element's parent element
    const wcParent = this.parentNode;

    function countWords(node) {
      const text = node.innerText || node.textContent;
      return text
        .trim()
        .split(/\s+/g)
        .filter((a) => a.trim().length > 0).length;
    }

    const count = `Words: ${countWords(wcParent)}`;

    // Create a shadow root
    const shadow = this.attachShadow({ mode: "open" });

    // Create text node and add word count to it
    const text = document.createElement("span");
    text.textContent = count;

    // Append it to the shadow root
    shadow.appendChild(text);

    // Update count when element content changes
    this.parentNode.addEventListener("input", () => {
      text.textContent = `Words: ${countWords(wcParent)}`;
    });
  }
}

// Define the new element
customElements.define("word-count", WordCount, { extends: "p" });

Disabling shadow DOM

If the element has a static property named disabledFeatures, which is an array containing the string "shadow", then the attachShadow() call will throw an exception.

For example:

js
class MyCustomElement extends HTMLElement {
  // Disable shadow DOM for this element.
  static disabledFeatures = ["shadow"];

  constructor() {
    super();
  }

  connectedCallback() {
    // Create a shadow root.
    // This will throw an exception.
    const shadow = this.attachShadow({ mode: "open" });
  }
}

// Define the new element
customElements.define("my-custom-element", MyCustomElement);

Specifications

Specification
DOM
# dom-element-attachshadow

Browser compatibility

desktop mobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
attachShadow
Chrome – Full support
Chrome 53 (Release date: 2016-08-31)
footnote Full support
Edge – Full support
Edge 79 (Release date: 2020-01-15)
footnote Full support
Firefox – Full support
Firefox 63 (Release date: 2018-10-23)
footnote Full support
Opera – Full support
Opera 40 (Release date: 2016-09-20)
footnote Full support
Safari – Full support
Safari 10 (Release date: 2016-09-20)
footnote Full support
Chrome Android – Full support
Chrome Android 53 (Release date: 2016-09-07)
footnote Full support
Firefox for Android – Full support
Firefox for Android 63 (Release date: 2018-10-23)
footnote Full support
Opera Android – Full support
Opera Android 41 (Release date: 2016-10-25)
footnote Full support
Safari on iOS – Full support
Safari on iOS 10 (Release date: 2016-09-13)
footnote Full support
Samsung Internet – Full support
Samsung Internet 6 (Release date: 2017-08-23)
footnote Full support
WebView Android – Full support
WebView Android 53 (Release date: 2016-09-07)
footnote Full support
WebView on iOS – Full support
WebView on iOS 10 (Release date: 2016-09-13)
footnote Full support
options.clonable parameter
Chrome – Full support
Chrome 124 (Release date: 2024-04-16)
footnote Full support
Edge – Full support
Edge 124 (Release date: 2024-04-18)
footnote Full support
Firefox – Full support
Firefox 123 (Release date: 2024-02-20)
footnote Full support
Opera – Full support
Opera 110 (Release date: 2024-05-14)
footnote Full support
Safari – Full support
Safari 16.4 (Release date: 2023-03-27)
altname
altname Alternate name: cloneable
Safari – Full support
Safari 17.4 (Release date: 2024-03-05)
footnote Full support
Chrome Android – Full support
Chrome Android 124 (Release date: 2024-04-16)
footnote Full support
Firefox for Android – Full support
Firefox for Android 123 (Release date: 2024-02-20)
footnote Full support
Opera Android – Full support
Opera Android 82 (Release date: 2024-05-02)
footnote Full support
Safari on iOS – Full support
Safari on iOS 16.4 (Release date: 2023-03-27)
altname
altname Alternate name: cloneable
Safari on iOS – Full support
Safari on iOS 17.4 (Release date: 2024-03-05)
footnote Full support
Samsung Internet – Full support
Samsung Internet 27 (Release date: 2024-11-06)
footnote Full support
WebView Android – Full support
WebView Android 124 (Release date: 2024-04-16)
footnote Full support
WebView on iOS – Full support
WebView on iOS 16.4 (Release date: 2023-03-27)
altname
altname Alternate name: cloneable
WebView on iOS – Full support
WebView on iOS 17.4 (Release date: 2024-03-05)
footnote Full support
options.delegatesFocus parameter
Chrome – Full support
Chrome 53 (Release date: 2016-08-31)
footnote Full support
Edge – Full support
Edge 79 (Release date: 2020-01-15)
footnote Full support
Firefox – Full support
Firefox 94 (Release date: 2021-11-02)
footnote Full support
Opera – Full support
Opera 40 (Release date: 2016-09-20)
footnote Full support
Safari – Full support
Safari 13.1 (Release date: 2020-03-24)
footnote Full support
Chrome Android – Full support
Chrome Android 53 (Release date: 2016-09-07)
footnote Full support
Firefox for Android – Full support
Firefox for Android 94 (Release date: 2021-11-02)
footnote Full support
Opera Android – Full support
Opera Android 41 (Release date: 2016-10-25)
footnote Full support
Safari on iOS – Full support
Safari on iOS 13.4 (Release date: 2020-03-24)
footnote Full support
Samsung Internet – Full support
Samsung Internet 6 (Release date: 2017-08-23)
footnote Full support
WebView Android – Full support
WebView Android 53 (Release date: 2016-09-07)
footnote Full support
WebView on iOS – Full support
WebView on iOS 13.4 (Release date: 2020-03-24)
footnote Full support
options.referenceTarget parameter
Experimental Non-standard
Chrome – No support
Chrome 133 (Release date: 2025-02-04)
disabled
disabled From version 133 users must explicitly set the #enable-experimental-web-platform-features preference to true. To change preferences in Chrome, visit chrome://flags.
Edge – No support
Edge 133 (Release date: 2025-02-06)
disabled
disabled From version 133 users must explicitly set the #enable-experimental-web-platform-features preference to true. To change preferences in Edge, visit about:flags.
Firefox – No support
Firefox 144 (Release date: 2025-10-14)
disabled
disabled From version 144 users must explicitly set the dom.shadowdom.referenceTarget.enabled preference to true. To change preferences in Firefox, visit about:config.
Opera – No support
Opera 118 (Release date: 2025-04-15)
disabled
disabled From version 118 users must explicitly set the #enable-experimental-web-platform-features preference to true. To change preferences in Opera, visit opera://flags.
Safari – No support
Safari 26 (Release date: 2025-09-15)
disabled
disabled From version 26 users must explicitly set the referenceTarget preference to true.
disabled From version 26 users must explicitly set the referenceTarget support for aria-owns preference to true.
Chrome Android – No support
Chrome Android 133 (Release date: 2025-02-04)
disabled
disabled From version 133 users must explicitly set the #enable-experimental-web-platform-features preference to true. To change preferences in Chrome Android, visit chrome://flags.
Firefox for Android – No support
Firefox for Android
footnote No support
Opera Android – No support
Opera Android
footnote No support
Safari on iOS – No support
Safari on iOS 26 (Release date: 2025-09-15)
disabled
disabled From version 26 users must explicitly set the referenceTarget preference to true.
disabled From version 26 users must explicitly set the referenceTarget support for aria-owns preference to true.
Samsung Internet – No support
Samsung Internet
footnote No support
WebView Android – No support
WebView Android
footnote No support
WebView on iOS – No support
WebView on iOS
footnote No support
options.serializable parameter
Chrome – Full support
Chrome 125 (Release date: 2024-05-14)
footnote Full support
Edge – Full support
Edge 125 (Release date: 2024-05-17)
footnote Full support
Firefox – Full support
Firefox 128 (Release date: 2024-07-09)
footnote Full support
Opera – Full support
Opera 111 (Release date: 2024-06-12)
footnote Full support
Safari – Full support
Safari 18 (Release date: 2024-09-16)
footnote Full support
Chrome Android – Full support
Chrome Android 125 (Release date: 2024-05-14)
footnote Full support
Firefox for Android – Full support
Firefox for Android 128 (Release date: 2024-07-09)
footnote Full support
Opera Android – Full support
Opera Android 83 (Release date: 2024-06-25)
footnote Full support
Safari on iOS – Full support
Safari on iOS 18 (Release date: 2024-09-16)
footnote Full support
Samsung Internet – Full support
Samsung Internet 27 (Release date: 2024-11-06)
footnote Full support
WebView Android – Full support
WebView Android 125 (Release date: 2024-05-14)
footnote Full support
WebView on iOS – Full support
WebView on iOS 18 (Release date: 2024-09-16)
footnote Full support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
No support
No support
Experimental. Expect behavior to change in the future.
Non-standard. Check cross-browser support before using.
User must explicitly enable this feature.
Uses a non-standard name
Has more compatibility info.

See also