HTML

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 要素

<template>要素とは?

HTMLの<template>要素は、ブラウザ上では表示されない(レンダリングされない)テンプレート用のコンテンツを定義するための要素です。DOMに読み込まれるものの、実際のページには反映されず“待機状態”になり、JavaScriptなどで必要に応じて複製し、表示・挿入することで動的なページを作成できます。

なぜ<template>が必要なのか

過去には、動的なコンテンツを生成するとき、以下のような手法がよく使用されていました。

しかし、これらは可読性が低い、構造とロジックが混ざりやすいなどの課題がありました。そこで、HTML5で登場した<template>要素を用いることで、HTML構造をそのままテンプレートとして記述しつつ、表示させたいタイミングでJavaScriptを使ってDOMに注入するという、より明確な設計が可能になりました。

<template>要素の基本的な使い方

基本構文

HTML

<template id="my-template">
	<div class="item">
		<h2>ここにタイトル</h2>
		<p>ここに説明文</p>
	</div>
</template>

テンプレートの内容を取得・複製し、表示する手順

  1. JavaScriptで<template>要素を取得

    JavaScript

    const template = document.getElementById('my-template');
  2. テンプレートの**内容(template.contentプロパティ)**をクローン(複製)する

    JavaScript

    // trueを指定すると、ディープクローン(中の要素全てを含めた複製)になる
    const clone = template.content.cloneNode(true);
  3. 複製した内容を、好きな場所に挿入する

    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>要素の特徴と注意点

ブラウザ上で非表示かつ“inert”な状態

<template>要素の内部に記述したコンテンツは、DOMとしては読み込まれますが、レンダリングされずまたユーザー操作の対象にもなりません。これを“inert”と呼びます。たとえば、テンプレートの中の画像が事前に読み込まれることもありません(<img>タグの場合は一部実装による差異があるので要注意)。

互換性・サポート状況

主要なモダンブラウザ(Chrome、Firefox、Edge、Safariなど)では、現在<template>要素はほぼサポートされています。一部の古いブラウザではサポートされていない場合がありますが、モダンWeb開発では必須といえるほど広く使われています。

Data on support for the mdn-html__elements__template feature across the major browsers from caniuse.com

SEOやSSRへの影響

<template>要素内のコンテンツは、通常のHTMLのように検索エンジンから認識されにくい場合があります。SEO観点で評価されたいテキストを<template>内に置く場合は、レンダリングされるかどうかを考慮しましょう。サーバーサイドレンダリング(SSR)でテンプレートを利用する場合でも、最終的に動的に生成されたDOMとして検索エンジンに評価されるかどうかは、検索エンジンによるレンダリングの対応状況に依存します。

応用的な使い方

変数を差し込む・コンテンツを動的に書き換える

テンプレートをクローンしたあと、JavaScriptで要素を操作して内容を書き換えることができます。例として、テンプレート内のテキストを差し替える方法を見てみましょう。

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操作を行って、実際の表示内容として挿入することで、動的で再利用性の高いパターンを作ることができます。

Web Components(カスタム要素)との組み合わせ

<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)との併用

SSRでHTMLを生成しつつ、クライアントサイドでも動的に要素を追加したい場合に<template>を利用する場面があります。SSRで一部のデータを埋め込んだ状態の<template>を生成し、クライアントサイドでは必要に応じて差し替えや追加を行うといったハイブリッドなアプローチも可能です。

イベントのデリゲーションとの組み合わせ

複製した要素が多数になる場合、それぞれにイベントリスナを付与するとパフォーマンスや可読性が悪化しがちです。そこでイベントのデリゲーションを使えば、一括でイベントを管理しつつ<template>による動的生成が行えます。

よくある疑問・トラブルシューティング

テンプレート内のスクリプトは実行される?

<template>内に<script>を記述しても、テンプレートの段階では実行されません。クローン後にDOMとして挿入されたとしても、多くのブラウザでは再度スクリプトを実行しません。そのため、動的にスクリプトを埋め込む必要がある場合は別途イベントハンドラを設定するか、JavaScriptファイルで制御することをおすすめします。

テンプレートがレンダリングされない・反映されない

テンプレートを複製していない
cloneNode(true)などでクローンしたものをDOMに挿入する必要があります。
セレクタの指定ミス
document.getElementByIdquerySelectorで正しく取得できているか確認してください。
<template>のサポートがない(古いブラウザ)
ポリフィルを使うか、フレームワークを介してテンプレート機能を実装しましょう。

<template>の内容がSEOで評価されない

Googleなど主要検索エンジンはJavaScriptでレンダリングされた内容も一定程度評価しますが、インデックスに反映されるまでに時間がかかる場合や、正しく評価されないケースもあります。SEOが重要なページでは、サーバーサイドレンダリングやプリレンダを検討すると良いでしょう。

まとめ