The <template>
element in HTML is an element that defines a draft HTML structure invisible in the browser, allowing it to be cloned, reused, and dynamically inserted as needed using JavaScript or similar means.
<template>
要素とは?HTMLの<template>
要素は、ブラウザ上では表示されない(レンダリングされない)テンプレート用のコンテンツを定義するための要素です。DOMに読み込まれるものの、実際のページには反映されず“待機状態”になり、JavaScriptなどで必要に応じて複製し、表示・挿入することで動的なページを作成できます。
<template>
が必要なのか過去には、動的なコンテンツを生成するとき、以下のような手法がよく使用されていました。
<script type="text/x-template">
などのスクリプトタグを疑似テンプレートとして使うしかし、これらは可読性が低い、構造とロジックが混ざりやすいなどの課題がありました。そこで、HTML5で登場した<template>
要素を用いることで、HTML構造をそのままテンプレートとして記述しつつ、表示させたいタイミングでJavaScriptを使ってDOMに注入するという、より明確な設計が可能になりました。
<template>
要素の基本的な使い方HTML
<template id="my-template">
<div class="item">
<h2>ここにタイトル</h2>
<p>ここに説明文</p>
</div>
</template>
id
やclass
はつけても構いませんが、通常はテンプレートを取得するためにid
を指定します。<template>
要素を取得
JavaScript
const template = document.getElementById('my-template');
template.content
プロパティ)**をクローン(複製)する
JavaScript
// trueを指定すると、ディープクローン(中の要素全てを含めた複製)になる
const clone = template.content.cloneNode(true);
JavaScript
const container = document.querySelector('#container');
container.appendChild(clone);
結果として、<template>
要素内に記述した構造が画面上に表示されるようになります。
テンプレートのタイトル
テンプレートの説明文がここに入ります。
HTML
<template id="my-template">
<div class="item">
<p class="head2">テンプレートのタイトル</p>
<p>テンプレートの説明文がここに入ります。</p>
</div>
</template>
<div id="container"></div>
<button id="show-template">テンプレートを表示</button>
<script>
document.getElementById('show-template').addEventListener('click', function() {
const template = document.getElementById('my-template');
const clone = template.content.cloneNode(true);
document.getElementById('container').appendChild(clone);
});
</script>
上記の例では、「テンプレートを表示」ボタンをクリックするたびに、テンプレートに記述された要素が複製されて#container
内に追加されていきます。
<template>
要素の特徴と注意点<template>
要素の内部に記述したコンテンツは、DOMとしては読み込まれますが、レンダリングされずまたユーザー操作の対象にもなりません。これを“inert”と呼びます。たとえば、テンプレートの中の画像が事前に読み込まれることもありません(<img>
タグの場合は一部実装による差異があるので要注意)。
主要なモダンブラウザ(Chrome、Firefox、Edge、Safariなど)では、現在<template>
要素はほぼサポートされています。一部の古いブラウザではサポートされていない場合がありますが、モダンWeb開発では必須といえるほど広く使われています。
<template>
要素内のコンテンツは、通常のHTMLのように検索エンジンから認識されにくい場合があります。SEO観点で評価されたいテキストを<template>
内に置く場合は、レンダリングされるかどうかを考慮しましょう。サーバーサイドレンダリング(SSR)でテンプレートを利用する場合でも、最終的に動的に生成されたDOMとして検索エンジンに評価されるかどうかは、検索エンジンによるレンダリングの対応状況に依存します。
テンプレートをクローンしたあと、JavaScriptで要素を操作して内容を書き換えることができます。例として、テンプレート内のテキストを差し替える方法を見てみましょう。
Name
HTML
<template id="user-card">
<div class="user-card">
<h2 class="user-name">Name</h2>
<p class="user-email">Email</p>
</div>
</template>
<div id="container2"></div>
<script>
const template = document.getElementById('user-card');
function createUserCard(name, email) {
// テンプレートを複製
const clone = template.content.cloneNode(true);
// テンプレート内の要素を取得して書き換え
clone.querySelector('.user-name').textContent = name;
clone.querySelector('.user-email').textContent = email;
return clone;
}
// 例: 複数ユーザーを表示
const users = [
{ name: '山田太郎', email: 'taro@example.com' },
{ name: '佐藤花子', email: 'hanako@example.com' }
];
const container = document.getElementById('container2');
users.forEach(user => {
container.appendChild(createUserCard(user.name, user.email));
});
</script>
このように、テンプレートを複製後にDOM操作を行って、実際の表示内容として挿入することで、動的で再利用性の高いパターンを作ることができます。
<template>
要素は、Web Componentsでカスタム要素を定義するときにもよく使われます。たとえば、以下のように<template>
を定義し、それをShadow DOMに適用することで、コンポーネントの再利用をより効率的に行えます。
HTML
<template id="my-element-template">
<style>
:host {
display: block;
background: #f8f8f8;
}
.content {
padding: 10px;
}
</style>
<div class="content">
<slot></slot>
</div>
</template>
<script>
class MyElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
const template = document.getElementById('my-element-template');
shadow.appendChild(template.content.cloneNode(true));
}
}
customElements.define('my-element', MyElement);
</script>
<!-- 使用例 -->
<my-element>
ここにユーザーの自由な内容を差し込める
</my-element>
<slot>
要素を使ったコンテンツ差し込みなども含め、<template>
要素とWeb Componentsは非常に相性が良いです。
JavaScriptのループを使ってテンプレートを大量に生成することで、リスト表示やテーブル表示などを効率よく行えます。また、プロパティの変更やイベントのバインドも複製のたびに行えるため、リアクティブなUIを作るときにも便利です。
JavaScript
// テーブルの行テンプレートを繰り返し挿入するなど
for (let i = 0; i < 10; i++) {
const clone = template.content.cloneNode(true);
// ここでclone内のセルのテキストや属性を変更
tableBody.appendChild(clone);
}
<template>
と<script type="text/x-template">
の違いかつてはVue.jsなどのフレームワークで<script type="text/x-template">
をテンプレートとして利用する手法がよく見られました。<template>
要素の未サポートブラウザへの対応や、フレームワーク独自の制御フローのために用いられてきましたが、現代のブラウザ環境では<template>
要素が標準的であり、より直感的にHTML構造を利用できるため、積極的に置き換えが進んでいます。
SSRでHTMLを生成しつつ、クライアントサイドでも動的に要素を追加したい場合に<template>
を利用する場面があります。SSRで一部のデータを埋め込んだ状態の<template>
を生成し、クライアントサイドでは必要に応じて差し替えや追加を行うといったハイブリッドなアプローチも可能です。
複製した要素が多数になる場合、それぞれにイベントリスナを付与するとパフォーマンスや可読性が悪化しがちです。そこでイベントのデリゲーションを使えば、一括でイベントを管理しつつ<template>
による動的生成が行えます。
<template>
内に<script>
を記述しても、テンプレートの段階では実行されません。クローン後にDOMとして挿入されたとしても、多くのブラウザでは再度スクリプトを実行しません。そのため、動的にスクリプトを埋め込む必要がある場合は別途イベントハンドラを設定するか、JavaScriptファイルで制御することをおすすめします。
cloneNode(true)
などでクローンしたものをDOMに挿入する必要があります。document.getElementById
やquerySelector
で正しく取得できているか確認してください。<template>
のサポートがない(古いブラウザ)<template>
の内容がSEOで評価されないGoogleなど主要検索エンジンはJavaScriptでレンダリングされた内容も一定程度評価しますが、インデックスに反映されるまでに時間がかかる場合や、正しく評価されないケースもあります。SEOが重要なページでは、サーバーサイドレンダリングやプリレンダを検討すると良いでしょう。
<template>
要素は、HTML内で直接コンテンツ構造を定義しながら、ブラウザ上では表示させず、必要時にJavaScriptでクローンしてDOMに挿入できる便利な要素です。