タイトル: template要素
SEOタイトル: HTML template要素 完全ガイド(クライアント側テンプレート / content / cloneNode / Web Components)
| この記事の要点 |
|
template要素とは
は HTML5 で追加された要素で、「ページには描画したくないが、JS から取り出して使いたい HTML 断片」を埋め込むためのものです。中身はパース時に DOM ツリー化されますが、レンダリングされず、スクリプトも実行されず、画像も読み込まれません。一覧表示の繰り返しブロックや、Web Components の Shadow DOM のテンプレートとして使われます。
基本構文
<template id="card-template">
<div class="card">
<h3 class="title"></h3>
<p class="body"></p>
<button class="more">詳しく</button>
</div>
</template>
<div id="list"></div>
<script>
const tpl = document.getElementById('card-template');
const list = document.getElementById('list');
const data = [
{ title: '記事A', body: '本文A' },
{ title: '記事B', body: '本文B' },
];
for (const item of data) {
const node = tpl.content.cloneNode(true); // 深いコピー
node.querySelector('.title').textContent = item.title;
node.querySelector('.body').textContent = item.body;
list.appendChild(node);
}
</script>
特徴
- 中身は document fragment として保持される(
template.content) - 描画されない(display:none を書く必要すらない)
- 中の
<img>や<script>は読み込まれない・実行されない - HTML として不正な入れ子も書ける(
<tr>単体など) - JS で複製してから DOM に挿入するのが基本パターン
innerHTML との比較
| 項目 | innerHTML で連結 | + cloneNode |
|---|---|---|
| パース | 毎回 HTML 文字列をパース | 初回 1 回だけ |
| 速度 | 遅い | 速い |
| XSS | 注意必要(文字列連結で混入しやすい) | safer(textContent で代入できる) |
| イベント | 後から再付与 | テンプレート側に書ける(複製後付与) |
| 可読性 | JS 内の文字列が肥大 | HTML と JS が分離 |
tr / td など不正な入れ子も書ける
通常の HTML では <table> の外に <tr> を書くと自動的に取り除かれてしまいますが、<template> の中であればテーブル断片だけを保持できます。
<template id="row-template">
<tr>
<td class="name"></td>
<td class="email"></td>
</tr>
</template>
<table>
<tbody id="tbody"></tbody>
</table>
Web Components との組み合わせ
Custom Elements の Shadow DOM を初期化するときに <template> がよく使われます。
const tpl = document.createElement('template');
tpl.innerHTML = `
<style>
.greet { color: tomato; font-weight: bold; }
</style>
<p class="greet">Hello, <slot name="name">World</slot>!</p>
`;
class HelloElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' })
.appendChild(tpl.content.cloneNode(true));
}
}
customElements.define('x-hello', HelloElement);
と の違い
- : ページに描画されないテンプレート定義。JS から取り出して使う
: Shadow DOM 内で外部から挿入される箇所を示す。Web Components の差し込み穴
よくある落とし穴
tpl.cloneNode(true)をすると ごとコピーされる — 使いたいのは中身なのでtpl.content.cloneNode(true)を使う- 同じ要素を直接 appendChild すると、最後の 1 つだけ DOM に移動してしまう(複製しないと使い回せない)
- 中身は描画されないので CSS のセレクタも当たらない(複製後に当たる)
- IE11 は未対応(モダンブラウザは全対応)