<template>: コンテンツテンプレート要素

<template>HTML の要素で、ページが読み込まれたときにすぐにレンダリングされるのではなく、実行時に JavaScript を使って後からインスタンス化することができる HTML を保持するためのメカニズムです。

テンプレートは、文書内に格納されたコンテンツの断片として考えてください。ページの読み込み時にパーサーが <template> 要素の内容を処理している間、その内容の有効性のみが検証されます。しかし、要素の内容は描画されません。

属性

<template> 要素が対応している標準的な属性は、グローバル属性のみです。

Chromium ベースのブラウザーでは、<template> 要素は標準外の shadowrootmode 属性 にも、実験的な "Declarative Shadow DOM" 提案の一部として対応しています。対応しているブラウザーでは、<template> 要素が shadowrootmode 属性を持っていることが HTML パーサーによって検出され、直ちに親要素のシャドウルートとして適用されます。shadowrootmodeopenclosed のどちらかの値を取ります。これらは Element.attachShadow()mode オプションの openclosed の値に相当します。

また、対応する HTMLTemplateElement インターフェイスは標準で content プロパティを持ち(同等のコンテンツ/マークアップ属性はなく)、読み取り専用の DocumentFragment で、テンプレートが表現する DOM サブツリーを保持しています。なお、content プロパティの値を直接使用すると予想外の動作につながる可能性があります。詳しくは、下記の DocumentFragment の落とし穴の回避の節を参照してください。

まず、HTML 部分の例から始めましょう。

html
<table id="producttable">
  <thead>
    <tr>
      <td>UPC_Code</td>
      <td>Product_Name</td>
    </tr>
  </thead>
  <tbody>
    <!-- existing data could optionally be included here -->
  </tbody>
</table>

<template id="productrow">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</template>

まず、JavaScript コードを使用して後からコンテンツを挿入するための表を作ります。次に、1 行分を表す HTML 断片の構造が書かれたテンプレートが続きます。

表が生成され、テンプレートが定義されました。 JavaScript を使って、テンプレートを基に構築される各行を表に挿入します。

js
// 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 の表ができます。

DocumentFragment の落とし穴の回避

DocumentFragment は様々なイベントのために有効なターゲットではないので、その中の要素を複製したり、参照したりすることが好ましいことがよくあります。

以下の HTML および JavaScript を考えてみてください。

HTML

html
<div id="container"></div>

<template id="template">
  <div>クリックしてください</div>
</template>

JavaScript

js
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.firstElementChild.cloneNode(true);
secondClone.addEventListener("click", clickHandler);
container.appendChild(secondClone);

結果

firstClone は DocumentFragment のインスタンスなので、期待通りにコンテナー内に追加されますが、クリックしてもクリックイベントは発生しません。 secondCloneHTMLDivElement のインスタンスなので、クリックすると期待通りに動作します。

技術的概要

コンテンツカテゴリー メタデータコンテンツ, フローコンテンツ, 記述コンテンツ, スクリプト対応要素
許可されている内容 制限なし
タグの省略 不可。開始と終了タグの両方が必要。
許可されている親要素 メタデータコンテンツ, 記述コンテンツ, スクリプト対応要素 を受け付けるすべての要素。また、 span 属性を持たない <colgroup> 要素の子になることもできます。
暗黙の ARIA ロール 対応するロールなし
許可されている ARIA ロール 許可されている role なし
DOM インターフェイス HTMLTemplateElement

仕様書

Specification
HTML Standard
# the-template-element

ブラウザーの互換性

BCD tables only load in the browser

関連情報