Element: attachShadow() メソッド

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.

Element.attachShadow() メソッドは、シャドウ DOM ツリーを特定の要素に追加し、そのシャドウルート (ShadowRoot) への参照を返します。

シャドウツリーを追加できる要素

シャドウルートはすべての要素に追加できるわけではありません。セキュリティ上の理由でシャドウ DOM を持てないものもあります(<a> など)。

以下にシャドウルートを追加できる要素を列挙します。

構文

js
attachShadow(options)

引数

options

以下のフィールドを含むオブジェクトです。

mode

文字列で、シャドウ DOM ツリーのカプセル化モードを指定します。 以下のいずれかをの値を取ります。

open

シャドウルートの要素には、例えば Element.shadowRoot を使用して、ルートの外部の JavaScript からアクセスできます。

js
element.attachShadow({ mode: "open" });
element.shadowRoot; // ShadowRoot オブジェクトを返す
closed

閉じたシャドウルートに対する外部の JavaScript からのアクセスを拒否します。

js
element.attachShadow({ mode: "closed" });
element.shadowRoot; // null を返す
delegatesFocus 省略可

論理値で、 true に設定された場合、フォーカス可能性に関するカスタム要素の問題を緩和します。シャドウ DOM のフォーカスができない部分がクリックされた場合、最初のフォーカス可能な部分がフォーカスを得て、シャドウホストは :focus のスタイルを利用することができます。既定値は false です。

slotAssignment 省略可

シャドウ DOM ツリーの スロット割り当てモード を指定します。これは以下のいずれかです。

named

要素は自動的にこのシャドウルート内の <slot> 要素に割り当てられます。このシャドウルート内の <slot>name 属性と一致する slot 属性を持つホスティングの子孫は、そのスロットに割り当てられます。ホスティングの最上位の子で slot 属性を持たないものは、 name 属性を持たない <slot>(「既定のスロット」)が存在する場合、そのスロットに割り当てられます。

manual

要素は自動的に <slot> 要素に割り当てることはできません。代わりに、HTMLSlotElement.assign() で手動で割り当てる必要があります。 既定値は named です。

返値

ShadowRoot オブジェクトです。

例外

InvalidStateError DOMException

取り付けようとしている要素が既にシャドウホストである場合。

NotSupportedError DOMException

シャドウルートを HTML 名前空間外の要素に取り付けようとした場合、シャドウを取り付けられない要素であった場合、要素の定義で静的プロパティ disabledFeatures"shadow" の値であった場合。

以下の例は word-count-web-component のデモを使用しています(実行例)。 コードの途中で attachShadow() を使ってシャドウルートを作成し、そこにカスタム要素の中身を取り付けているのがわかると思います。

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
    setInterval(() => {
      const count = `Words: ${countWords(wcParent)}`;
      text.textContent = count;
    }, 200);
  }
}

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

仕様書

Specification
DOM Standard
# ref-for-dom-element-attachshadow①

ブラウザーの互換性

BCD tables only load in the browser

関連情報