Element: attachShadow() method
BaselineWidely 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.
TheElement.attachShadow()
method attaches a shadow DOM tree to the specified element and returns a reference to itsShadowRoot
.
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 youcan 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 adeclarative shadow root, provided the specified modemode
matches the existing mode.In this case theShadowRoot
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 callingattachShadow()
on an element that already has a shadow root will throw an exception.
Syntax
attachShadow(options)
Parameters
options
An object which contains the following fields:
mode
A string specifying theencapsulation 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
:jselement.attachShadow({ mode: "open" });element.shadowRoot; // Returns a ShadowRoot obj
closed
Denies access to the node(s) of a closed shadow rootfrom JavaScript outside it:
jselement.attachShadow({ mode: "closed" });element.shadowRoot; // Returns null
clonable
OptionalA boolean that specifies whether the shadow root is clonable: when set to
true
, the shadow host cloned withNode.cloneNode()
orDocument.importNode()
will include shadow root in the copy. Its default value isfalse
.delegatesFocus
OptionalA 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 isfalse
.serializable
OptionalA boolean that, when set to
true
, indicates that the shadow root is serializable.If set, the shadow root may be serialized by calling theElement.getHTML()
orShadowRoot.getHTML()
methods with theoptions.serializableShadowRoots
parameter settrue
.Its default value isfalse
.slotAssignment
OptionalA string specifying theslot 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 aslot
attribute which matches thename
attribute of a<slot>
within this shadow root will be assigned to that slot. Any top-level children of the host with noslot
attribute will be assigned to a<slot>
with noname
attribute (the "default slot") if one is present.manual
Elements are not automatically assigned to
<slot>
elements. Instead, they must be manually assigned withHTMLSlotElement.assign()
.Its default value isnamed
.
Return value
Returns aShadowRoot
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 adeclarative shadow root but the specified
mode
does not match the existing mode.
Examples
Word count custom element
The following example is taken from ourword-count-web-component demo (see it live also).You can see that we useattachShadow()
in the middle of the code to create a shadow root, which we then attach our custom element's contents to.
// Create a class for the elementclass 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 elementcustomElements.define("word-count", WordCount, { extends: "p" });
Disabling shadow DOM
If the element has a static property nameddisabledFeatures
, which is an array containing the string"shadow"
, then theattachShadow()
call will throw an exception.
For example:
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 elementcustomElements.define("my-custom-element", MyCustomElement);
Specifications
Specification |
---|
DOM # ref-for-dom-element-attachshadow① |
Browser compatibility
See also
ShadowRoot.mode
ShadowRoot.delegatesFocus
ShadowRoot.slotAssignment
- Declaratively attach a shadow root with the
shadowrootmode
attribute of the<template>
element - Declarative shadow DOM on web.dev (2023)