このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docsコミュニティーについてもっと知り、仲間になるにはこちらから。
<template>: コンテンツテンプレート要素
Baseline Widely available *
This feature is well established and works across many devices and browser versions. It’s been available across browsers since 2015年11月.
* Some parts of this feature may have varying levels of support.
<template> はHTML の要素で、HTML フラグメントを保持し、後で JavaScript を使用して使用したり、シャドウ DOM の中に即座に生成したりするためのメカニズムとして機能します。
In this article
属性
この要素にはグローバル属性があります。
shadowrootmode親要素のシャドウルートを生成します。これは
Element.attachShadow()メソッドの宣言版で、同じenumerated 値を受け入れます。メモ:HTML パーサーは、この属性が設定されているノードの最初の
<template>に対して、DOM にShadowRootオブジェクトを作成します。この属性が設定されていない場合、または許可された値が設定されていない場合、あるいはShadowRootが既に同じ親に宣言的に作成されている場合は、HTMLTemplateElementが作成されます。HTMLTemplateElementは、HTMLTemplateElement.shadowRootModeを設定したりすることで、解釈後にシャドウルートに変更することはできません。メモ:古いチュートリアルや例では、Chrome 90-110 で対応していた非標準の
shadowroot属性が見つかるかもしれません。この属性は削除され、標準のshadowrootmode属性に置き換えられています。shadowrootclonableこの要素を使用して作成した
ShadowRootのclonableプロパティの値をtrueに設定します。設定されている場合、シャドウホスト(この<template>の親要素)の複製をNode.cloneNode()またはDocument.importNode()で作成すると、コピーにシャドウルートが含まれます。shadowrootdelegatesfocusこの要素を使用して作成した
ShadowRootのdelegatesFocusプロパティの値をtrueに設定します。これが設定されていて、シャドウツリー内のフォーカス可能でない要素が選択されている場合、フォーカスはツリー内の最初のフォーカス可能な要素に譲られます。この値はfalseが既定値です。shadowrootserializableExperimentalこの要素を使用して作成した
ShadowRootのserializableプロパティの値をtrueに設定します。設定されている場合、シャドウルートはElement.getHTML()またはShadowRoot.getHTML()メソッドを、options.serializableShadowRoots引数をtrueに設定して呼び出すことでシリアライズされます。この値はfalseが既定値です。
使用上のメモ
<template> 要素の主な用途は 2 つあります。
テンプレート文書フラグメント
既定では、要素のコンテンツはレンダリングされません。対応するHTMLTemplateElement インターフェイスは標準でcontent プロパティを含みます(同等の content/markup 属性はありません)。このcontent プロパティは読み取り専用で、テンプレートが表す DOM サブツリーを格納するDocumentFragment を保持します。このフラグメントはcloneNode メソッドで複製し、DOM に挿入することができます。
content プロパティを使用するときは、返値のDocumentFragment が予期せぬ挙動を示すことがあることに注意が必要です。詳細は下記のDocumentFragment の落とし穴を避ける節を参照してください。
宣言的シャドウ DOM
もし<template> 要素がshadowrootmode 属性の値open またはclosed を格納すると、HTML パーサーは直ちにシャドウ DOM を生成します。その要素はShadowRoot でラップされたコンテンツによって DOM 内で置き換えられ、親要素に装着されます。これはElement.attachShadow() を呼び出して要素にシャドウルートを付けるのと宣言的に等価です。
要素がshadowrootmode に他の値を示す場合、またはshadowrootmode 属性を持たない場合、パーサはHTMLTemplateElement を生成します。同様に、宣言的シャドウルートが複数ある場合、最初のシャドウルートのみがShadowRoot で置き換えられ、それ以降はHTMLTemplateElement オブジェクトとして解釈できます。
例
>表の行を生成
まず、HTML 部分の例から始めましょう。
<table> <thead> <tr> <td>UPC_Code</td> <td>Product_Name</td> </tr> </thead> <tbody> <!-- existing data could optionally be included here --> </tbody></table><template> <tr> <td></td> <td></td> </tr></template>まず、JavaScript コードを使用して後からコンテンツを挿入するための表を作ります。次に、1 行分を表す HTML 断片の構造が書かれたテンプレートが続きます。
表が生成され、テンプレートが定義されました。 JavaScript を使って、テンプレートを基に構築される各行を表に挿入します。
// templete 要素の content 属性の有無を確認することで、// ブラウザーが HTML の template 要素に対応しているかテストします。if ("content" in document.createElement("template")) { // 既存の HTML tbody と template の行を使って // table をインスタンス生成します。 const tbody = document.querySelector("tbody"); const template = document.querySelector("#productrow"); // 新しい行を複製して表に挿入します。 const clone = template.content.cloneNode(true); let td = clone.querySelectorAll("td"); td[0].textContent = "1235646565"; td[1].textContent = "Stuff"; tbody.appendChild(clone); // 新しい行を複製して表に挿入します。 const clone2 = template.content.cloneNode(true); td = clone2.querySelectorAll("td"); td[0].textContent = "0384928528"; td[1].textContent = "Acme Kidney Beans 2"; tbody.appendChild(clone2);} else { // HTML の template 要素に対応していないので // 表に行を追加するほかの方法を探します。}結果として、 JavaScript を通して、新しい行が追加された HTML の表ができます。
table { background: #000;}table td { background: #fff;}宣言的シャドウ DOM の実装
この例では、マークアップの始めに非表示で対応する警告を記載しています。この警告は後でブラウザーのshadowrootmode 属性に対応していない場合に JavaScript で表示するように設定します。次の記事には 2 つの<article> 要素があり、それぞれ異なる振る舞いをする<style> 要素を含んでいます。最初の<style> 要素は文書全体に対してグローバルです。2 つ目はshadowrootmode 属性が存在するため、<template> 要素の代わりに生成されたシャドウルートにスコープされます。
<p hidden> ⛔ Your browser doesn't support <code>shadowrootmode</code> attribute yet.</p><article> <style> p { padding: 8px; background-color: wheat; } </style> <p>I'm in the DOM.</p></article><article> <template shadowrootmode="open"> <style> p { padding: 8px; background-color: plum; } </style> <p>I'm in the shadow DOM.</p> </template></article>const isShadowRootModeSupported = HTMLTemplateElement.prototype.hasOwnProperty("shadowRootMode");document .querySelector("p[hidden]") .toggleAttribute("hidden", isShadowRootModeSupported);フォーカスを譲渡を伴う宣言的シャドウ DOM
この例では、shadowrootdelegatesfocus を宣言的に作成したシャドウルートに適用し、フォーカスにどのような効果があるかを示します。
このコードでは、最初に<template> 要素にshadowrootmode 属性を用いて、<div> 要素の中にシャドウルートを宣言します。これにより、テキストを格納したフォーカスできない<div> と、フォーカスできる<input> 要素の両方が表示されます。また、:focus を持つ要素を青にスタイル設定し、ホスト要素の通常のスタイル設定を設定するには CSS を使用します。
<div> <template shadowrootmode="open"> <style> :host { display: block; border: 1px dotted black; padding: 10px; margin: 10px; } :focus { outline: 2px solid blue; } </style> <div>Clickable Shadow DOM text</div> <input type="text" placeholder="Input inside Shadow DOM" /> </template></div>2 つ目のコードブロックは、shadowrootdelegatesfocus 属性を設定している以外は同じです。この属性は、ツリー内のフォーカス可能でない要素が選択された場合に、ツリー内の最初のフォーカス可能な要素にフォーカスを譲ったものです。
<div> <template shadowrootmode="open" shadowrootdelegatesfocus> <style> :host { display: block; border: 1px dotted black; padding: 10px; margin: 10px; } :focus { outline: 2px solid blue; } </style> <div>Clickable Shadow DOM text</div> <input type="text" placeholder="Input inside Shadow DOM" /> </template></div>最後に、以下の CSS を使用して、親要素である<div> にフォーカスがあるときに緑黄色の枠線を適用します。
div:focus { border: 2px solid red;}その結果を下記に示します。HTML は最初にレンダリングされるとき、最初の画像に示すように要素にはスタイル設定がありません。shadowrootdelegatesfocus が設定されていないシャドウルートでは、<input> 以外の場所をクリックしてもフォーカスは変わりません(<input> 要素を選択すると 2 つ目の画像のようになります)。

shadowrootdelegatesfocus を設定したシャドウルートでは、テキスト(フォーカスできない)をクリックすると、<input> 要素が選択されます。これは下記に示すように親要素もフォーカスされます。

DocumentFragment の落とし穴の回避
DocumentFragment の値が渡されると、Node.appendChild や同様のメソッドはその値の子ノードだけを対象とするノードに移動させます。したがって、イベントハンドラーはDocumentFragment 自体ではなく、DocumentFragment の子ノードに設定することが推奨されます。
以下の HTML および JavaScript を考えてみてください。
HTML
<div></div><template> <div>クリックしてください</div></template>JavaScript
const container = document.getElementById("container");const template = document.getElementById("template");function clickHandler(event) { event.target.append(" — この div がクリックされました");}const firstClone = template.content.cloneNode(true);firstClone.addEventListener("click", clickHandler);container.appendChild(firstClone);const secondClone = template.content.cloneNode(true);secondClone.children[0].addEventListener("click", clickHandler);container.appendChild(secondClone);結果
firstClone はDocumentFragment なので、appendChild が呼び出されたときにcontainer に追加されるのはその子ノードだけで、firstClone のイベントハンドラーはコピーされません。一方、secondClone は最初の子ノードにイベントハンドラーが追加されているため、appendChild が呼び出されるとイベントハンドラーがコピーされ、クリックすると期待通りに動作します。
技術的概要
| コンテンツカテゴリー | メタデータコンテンツ,フローコンテンツ,記述コンテンツ,スクリプト対応要素 |
|---|---|
| 許可されている内容 | 制限なし |
| タグの省略 | なし。開始タグと終了タグの両方が必須です。 |
| 許可されている親要素 | メタデータコンテンツ,記述コンテンツ,スクリプト対応要素 を受け付けるすべての要素。また、span 属性を持たない<colgroup> 要素の子になることもできます。 |
| 暗黙の ARIA ロール | 対応するロールなし |
| 許可されている ARIA ロール | 許可されているrole なし |
| DOM インターフェイス | HTMLTemplateElement |
仕様書
| Specification |
|---|
| HTML> # the-template-element> |
ブラウザーの互換性
関連情報
partおよびexportparts属性<slot>要素:host、:host()、:host-context()擬似クラス::part、::slotted擬似要素ShadowRootインターフェイス- テンプレートとスロットの使用
- CSS スコープ化 モジュール
- 宣言的シャドウ DOM (HTML による) (シャドウ DOM の使用)
- Declarative shadow DOM (developer.chrome.com, 2023)