Shadow DOM を使用すると、コンポーネントの内部と、作成者時にカスタム要素のユーザーによって提供された要素との間の構成であるWebコンポーネントを作成できます。 これは、ネイティブselect要素内でoptionまたはoptgroup要素を使用する場合と同様です。 この構成は、 slot と呼ばれるメカニズムを使用して可能になります。ここでは、カスタム要素でスロットと名前付きスロットを使用して、興味深い構成を可能にする方法について説明します。

あなたの最初のスロットコンテンツ

カスタム要素のユーザーが独自のマークアップと要素を要素の一部として追加できるようにするのは、コンポーネントのテンプレートでslot要素を使用するのと同じくらい簡単です。

これは、要素が使用されるときに追加されるコンテンツのスタイル付きシェルとしてのみ機能するダムカスタム要素の例です。

my-info-box.js
(function() {
  const template = document.createElement('template');

  template.innerHTML = `
    <style>
      :host {
        display: block;
        contain: content;
        text-align: center;
        background: papayawhip;
        max-width: 500px;
        margin: 0 auto;
        box-shadow: 0 0 10px rgba(128, 100, 38, 0.34);
        border-radius: 8px;
        border: 2px dashed #ccc049;
      }
    </style>
<span class="code-annotation">&#x3C;slot&#x3E;&#x3C;/slot&#x3E;</span>  `;
  class MyInfoBox extends HTMLElement {
    constructor() {
      super();
  this.attachShadow({ mode: 'open' });
  this.shadowRoot.appendChild(template.content.cloneNode(true));
}  }

要素のスタイルに:host を使用することについて疑問に思っていますか? カスタム要素のスタイリングについてお読みください。

この要素は、次のように使用できます。

<my-info-box>
  <p>I'm slotted content!</p>
</my-info-box>

カスタム要素内に追加されたマークアップはlightDOM と呼ばれ、ChromeのDevToolsから見た要素のこのスクリーンショットからわかるように、ShadowDOMの範囲外にとどまります。

Shadow DOM vs Light DOM

ライトDOMの要素は、代わりに要素の子として直接アクセスできるため、通常DOMの要素にアクセスするのと同じように、次のようにして要素を取得できます。

const myInfoBox = document.querySelector('my-info-box');
const text = myInfoBox.children[0].innerText;

console.log(text); // I'm slotted content!

スロットで使用されている軽いDOM要素は、分散ノードと呼ばれます。

デフォルトのコンテンツ

要素が使用されているときに何も提供されない場合は、スロットにデフォルトのコンテンツを提供できます。

my-info-box.js(部分的)
<slot>
 <p>I'm some default content!</p>
</slot>

また、要素が次のように使用される場合、このデフォルトのコンテンツが使用されます。

<my-info-box></my-info-box>

名前付きスロット

要素のユーザーからさまざまなコンテンツを取得できるより複雑な要素の作成は、名前付きスロットを使用して簡単に行うことができます。 ここでは、名前付きスロットが通常のスロットと一緒に使用されている簡単な例を見ることができます。

my-info-box.js(部分的)
<div>
  <slot name="title"></slot>
  <hr>
  <slot></slot>
</div>

この場合、要素は次のように使用できます。

<my-info-box>
  <span slot="title">🍭 Fancy title</span>
  <p>I'm going straight to the anonymous slot.</p>
</my-info-box>

名前付きスロットのおかげで、複数のピースを一緒に構成する複雑なカスタム要素を簡単に作成できます。 たとえば、タイトル、ロゴ、左側のナビゲーションアイテム、および右側のナビゲーションアイテムを取得するナビゲーションバー。

::slottedを使用したスロットコンテンツのスタイリング

:: slotted()セレクターを使用して、スロット付きコンテンツのスタイルを設定できます。 非常に簡単な例を次に示します。

<style>
  ::slotted(span) {
    background: pink;
  }
  ::slotted(.content) {
    font-family: monospace;
  }
</style>

<div>
  <slot name="title"></slot>
  <hr>
  <slot></slot>
</div>

また、これにより、次の例のタイトルの背景はピンクになり、メインコンテンツは等幅フォントになります。

<my-info-box>
  <span slot="title">🍭 Fancy title</span>
  <p class="content">I'm going straight to the anonymous slot.</p>
</my-info-box>

:: slotted で使用されるセレクターは、ネストされた要素を使用するスロットと一致できないため、最上位の要素を選択する必要があることに注意してください。