--- title: テンプレートとスロットの使用 slug: Web/Web_Components/Using_templates_and_slots tags: - Template - ウェブコンポーネント - シャドウ DOM - slot - スロット translation_of: Web/Web_Components/Using_templates_and_slots --- {{DefaultAPISidebar("Web Components")}} この記事では、{{htmlelement("template")}} と {{htmlelement("slot")}} 要素を使用して柔軟なテンプレートを作成し、それをウェブコンポーネントのシャドウ DOM を表示するために使用する方法について説明します。 ## テンプレートの真実 ウェブページで同じマークアップ構造を繰り返し再利用する必要がある場合、同じ構造を何度も繰り返すよりも、何らかのテンプレートを使用する方が理にかなっています。 これは以前から可能でしたが、HTML の {{htmlelement("template")}} 要素によって、かなり容易になりました(最近のブラウザーはよく対応しています)。 この要素とその内容は DOM 内で描画されませんが、JavaScript を使って参照することは可能です。 簡単な例を見てみましょう。 ```html ``` これはページ上に表示されず、以下のようなコードで JavaScript で参照を取得し、 DOM に追加することで表示されます。 ```js let template = document.getElementById('my-paragraph'); let templateContent = template.content; document.body.appendChild(templateContent); ``` つまらない例ですが、すでに有用性は見えてきたでしょう。 ## ウェブコンポーネントを用いたテンプレートの使用 テンプレートはそれ自体でも便利ですが、ウェブコンポーネントと組み合わせるとさらに効果的です。 テンプレートをシャドウ DOM の内容として使用するウェブコンポーネントを定義してみましょう。 同様に `` と呼ぶことにします。 ```js customElements.define('my-paragraph', class extends HTMLElement { constructor() { super(); let template = document.getElementById('my-paragraph'); let templateContent = template.content; const shadowRoot = this.attachShadow({mode: 'open'}) .appendChild(templateContent.cloneNode(true)); } } ); ``` ここで、テンプレートの内容を使用するために {{domxref("Node.cloneNode()")}} メソッドを使用して複製したものをシャドウルートに追加していることに注意してください。 また、その内容をシャドウ DOM に追加しているため、テンプレート内のスタイル情報を {{htmlelement("style")}} 要素に含めることができ、それがカスタム要素内にカプセル化されます。 これは、単に標準 DOM に追加しただけでは機能しません。 したがって、例えば ```html ``` HTML 文書に次のように追加するだけで利用できるようになりました。 ```html ``` > **Note:** テンプレートはブラウザーの対応が進んでいます。 Shadow DOM API は既定で、 Firefox (バージョン 63 以降) 、Chrome、Opera、Safari、Edge (バージョン 79 以降) で対応しています。 ## スロットによる柔軟性の強化 ここまではいいのですが、この要素はあまり柔軟ではありません。 中には高々 1 つのテキストを表示できるだけなので、現時点では通常の段落よりも有用ではありません。 {{htmlelement("slot")}} 要素を使用することで、各要素インスタンスに異なるテキストを表示することを宣言的に行えるようにすることができます。 これは {{htmlelement("template")}} よりも対応が限定されており、Chrome 53, Opera 40, Safari 10, Firefox 59, Edge 79 から利用可能です。 スロットは `name` 属性で識別され、テンプレート内にプレイスホルダーを定義することができます。このプレースホルダーは、その要素がマークアップで使用されたときに、任意のマークアップフラグメントで埋められるようになります。 ですから、この些細な例にスロットを追加したい場合、テンプレートの段落要素を次のように更新してください。 ```html

既定のテキスト

``` マークアップに要素が含まれるときにスロットの内容が定義されていない場合、またはブラウザーがスロットに対応していない場合、 `` はに単に代替内容である「既定のテキスト」が入ります。 スロットの内容を定義するために、`` 要素の中に HTML 構造を入れ、 {{htmlattrxref("slot")}} 属性の値が埋めたいスロットの名前と同じになるようにします。前と同じように、これは好きなものを指定できます。 ```html 別なテキストを入れましょう。 ``` 以下のようにも設定できます。 ```html
  • 別なテキストを入れましょう。
  • リストの中です。
``` > **Note:** スロットに挿入できるのは _Slotable_ な要素に限られます; 要素がスロットに挿入されたとき、_slotted_ と呼ばれます。 > **Note:** 無名の {{HTMLElement("slot")}} には、カスタム要素のトップレベルの子ノードのうち {{htmlattrxref("slot")}} 属性を持たないすべてのノードが入ります。これにはテキストノードも含まれます。 簡単な例での説明は以上です。 もっと実行してみたい場合は、 [GitHub 上にあります](https://github.com/mdn/web-components-examples/tree/master/simple-template) ([ライブ実行版](https://mdn.github.io/web-components-examples/simple-template/)もあります)。

より踏み込んだ例

記事の最後に、もう少し本格的なものを見てみましょう。 以下の一連のコードは、 {{HTMLElement("slot")}} を {{HTMLElement("template")}} と若干の JavaScript と組み合わせて使用する方法を示すコードスニペットです。 - **``** 要素を[名前付きスロット](/ja/docs/Web/HTML/Element/slot#named-slot)付きで[シャドウルート](/ja/docs/Web/API/ShadowRoot)の中に作成する - **``** 要素を、文書内で使用されたとき、要素の内容とその[シャドウルート](/ja/docs/Web/API/ShadowRoot)の内容を組み合わせてレンダリングされるように設計します。つまり、要素の内容の断片は、その[シャドウルート](/ja/docs/Web/HTML/Element/slot#named-slot) の中で[名前付きスロット](/ja/docs/Web/API/ShadowRoot)を埋めるために使用されます。 なお、 {{HTMLElement("slot")}} 要素は技術的には、 {{HTMLElement("template")}} 要素なしで、例えば、通常の {{HTMLElement("div")}} 要素内で使うことも可能であり、それでもシャドウ DOM 内容に対して {{HTMLElement("slot")}} のプレースホルダー機能を活用することができますし、そうすれば、最初にテンプレート要素の `content` プロパティにアクセス(してそれを複製)する必要があるという小さなトラブルも実際に避けることができます。 しかし、一般的には {{HTMLElement("template")}} 要素内にスロットを追加する方がより実用的です。なぜなら、既にレンダリングされた要素に基づいてパターンを定義する必要があることはほとんどないからです。 また、まだレンダリングされていない場合でも、 {{HTMLElement("template")}} を使用することで、テンプレートとしてのコンテナーの目的がより意味的に明確になるはずです。また、 {{HTMLElement("template")}} には、 {{HTMLElement("td")}} のような、 {{HTMLElement("div")}} に追加すると消えてしまうような項目を直接追加することができます。 > **Note:** 完全な例は [element-details](https://github.com/mdn/web-components-examples/tree/master/element-details) で ([ライブ実行版](https://mdn.github.io/web-components-examples/element-details/)も) 参照することができます。 ### template をスロットと共に作成 まず最初に {{HTMLElement("slot")}} 要素を {{HTMLElement("template")}} 要素の中に作成し、[名前付きスロット](/ja/docs/Web/HTML/Element/slot#named-slot)を含んだ新しい "element-details-template" という[文書フラグメント](/ja/docs/Web/API/DocumentFragment)を作成します。 ```html ``` この {{HTMLElement("template")}} 要素にはいくつかの特徴があります。 - {{HTMLElement("template")}} には {{HTMLElement("style")}} 要素があり、 {{HTMLElement("template")}} が生成する文書の断片だけを対象とした CSS スタイルの集合を持ちます。 - {{HTMLElement("template")}} は {{HTMLElement("slot")}} とその {{htmlattrxref("name", "slot")}} 属性を用いて、 3 つの[名前付きスロット](/ja/docs/Web/HTML/Element/slot#named-slot) を生成しています。 - `` - `` - `` - {{HTMLElement("template")}} には[名前付きスロット](/ja/docs/Web/HTML/Element/slot#named-slot)を {{HTMLElement("details")}} 要素の中に持ちます。 ### 新しい \ 要素を \