templateタグ 👉 JavaScriptで後から挿入するHTML

HTMLの<template>タグ(コンテンツ・テンプレート要素)を使うと、JavaScriptで後から挿入するHTMLを保持しておくことができます。

<template>
  <h2>こんにちは!</h2>
  <p>はじめまして</p>
</template>

👆ブラウザが真っ白ですね。<template>内のHTMLは、ページ読み込み時には描画(表示)されません。<template>の中は、後からどこかに挿入したいHTMLを入れておく場所になります。

templateタグの基本

画像や動画などはダウンロードされない

<template>タグ内のHTMLは、そのままではブラウザに描画されません。たとえば、以下のようなHTMLの場合…

HTML
<template>
  ↓ここに画像
  <img src="/example.png">
</template>

👆<template>内の画像(<img>)は描画されないため、画像への読み込みリクエストも飛びません。動画や音声でも同じです。必要になるまでリソースのダウンロードを遅らせることができるのです。

display: noneを使うと…

<template>を使わなくても「必要になるまでCSSでdisplay :noneをあてとけば良いんじゃないの?」と思われる方もいるかもしれません。しかしdisplay :noneはブラウザ上で表示されないだけで、実際には画像などのファイルはダウンロードされます。

どこにでも置いてもOK

<template>はHTMLの中であれば<body>内だけじゃなく<head>タグ内に置いてもOKです。

HTML
<head>
  ...
  <template>
    <meta name="~" content="~">
    <link rel="stylesheet" href="/style.css" />
  </template>
  ...
</head>

どこに置いたとしても、コンテンツを取得して表示するときには好きな場所に挿入できます。

scriptタグも使える

HTML
<template>
  <div id="app"></div>
  <script src="~"></script>
  <script>
    console.log(document.getElementById("app"));
  </script>
</template>

👆<template>内に<script>タグを置いておき、有効化するタイミングでリソースを読み込んだり、スクリプトを実行することもできます。

document.getElementByIdではtemplate内のDOMを取得できない

<template id="template">
  <div id="example">...</div>
  👆document.getElementById('example')では取得できない
</template>

<template>内のコンテンツはドキュメント上に存在しないことになるため、document.getElementById()document.querySelector()でコンテンツ内の要素オブジェクトを直接取得することはできません。ではどうするかというと以下のようにします。

JavaScript コンテンツ内の要素を取得
// 1) template要素を取得
const template = document.getElementById('template');
// 2) コンテンツを取得
const content = template.content;

// 実際はここでcontentを複製する(のちほど解説)

// 3) コンテンツから要素を取り出す
const example = content.getElementById('example');

👆まずテンプレート・コンテンツ(template要素.content)を取得し、そのコンテンツ内の要素を取得する…という流れになります。

templateタグの使い方

コンテンツを有効化(挿入)する流れ

<template>内のコンテンツを有効化する(どこかに挿入する)手順は以下のようになります。

🍳コンテンツを挿入する流れ

  1. templateコンテンツを取得
  2. コンテンツを複製する
  3. コンテンツを操作する(必要な場合のみ)
  4. 実際に挿入する

簡単な例

まずはテンプレート・コンテンツを単純に<body>内に挿入するだけの例を見てみましょう。ボタンがクリックされたときに実行されるようにします。

HTML templateを配置
<!-- ボタン -->
<button id="btn" onclick="activateTemplate">実行する</button>

<!-- template -->
<template id="template">
  <div>挿入完了🎉</div>
  <script>alert('挿入されました!')</script>
</template>

👆コンテンツが挿入されると「挿入完了🎉」のテキストが表示されるとともに「挿入されました!」のアラートが表示されるはずです。

JavaScript コンテンツを挿入
// templateコンテンツを挿入する関数
const activateTemplate = () => {
  // ①コンテンツを取得
  const template = document.getElementById('template');
  const content = template.content;
  // ②複製する
  const clone = document.importNode(content, true);
  // ③とくに変更しない
  // ④挿入する
  document.body.appendChild(clone);
};

// ボタンがクリックされたときに実行
document.getElementById('btn').addEventListener('click', activateTemplate);

👆JavaScriptで、templateコンテンツの取得 → 複製 → 挿入の処理を書きます。以下で簡単に解説します。

①取得
getElementById()querySelector()でtemplate要素を取得します。コンテンツはtemplate要素.contentで取得できます。
②複製
document.importNode(content, true)でコンテンツを複製します。第2引数はtrueにしましょう(子ノードまで複製されます)。
③操作
今回は特にコンテンツを変更しません。
④挿入
好きな位置に挿入すればOKです。今回はdocument.body.appendChildでbodyタグ内に挿入します。

実際の動作を確認してみよう

👆ボタンのクリックにより<template>内のコンテンツが挿入されるのが分かると思います。元の<template>はそのままなので、別の処理からもコンテンツを利用できます。


モーダルを挿入するサンプル

つづいてもう少し実践的な例を考えてみましょう。

templateでモーダルを挿入するサンプル

メールアドレスの入力欄を埋めて送信すると「◯◯にメールを送信しました」とモーダルウィンドウで表示するサンプルを作ります。

HTML templateを配置
<!-- フォーム -->
<form id="form">
  <input type="email" id="email" placeholder="メールアドレス">
  <button type="submit" class="btn">登録する</button>
</form>
  
<!-- ここにコンテンツを挿入する-->
<div id="modal-container"></div>

<!-- templateコンテンツ -->
<template id="template-modal">
  <div class="modal-background">
    <div class="modal-content">
      <h2>メールを送信しました</h2>
      <p id="note"></p>
    </div>
  </div>
</template>

👆HTMLはこのようにします。フォームを用意しておき、送信されたときに<template>コンテンツを挿入します。

JavaScript コンテンツを挿入
const activateTemplate = () => {
  // 1. templateコンテンツを取得
  const templateModal = document.getElementById('template-modal');
  const content = templateModal.content;

  // 2. 複製
  const clone = document.importNode(content, true); // 第2引数はtrueにする(子ノードまで複製)
  
  // 3. 操作(メールアドレスをモーダルに表示)
  const email = document.getElementById('email').value;
  // ⭐複製コンテンツの#noteのテキストを設定
  clone.getElementById('note').innerText = `${email}にメールを送信しました`;
  
  // 4. 挿入
  document.getElementById('modal-container').appendChild(clone);
}

// フォーム送信時に実行
document.querySelector('#form').addEventListener('submit', e => {
  e.preventDefault();
  activateTemplate();
});

👆フォームが送信(submit)されたときにactivateTemplate()を実行します。

さきほどと違うのは複製したコンテンツを挿入前に変更している点です。複製コンテンツ.getElementById(~).innerText = テキストでコンテンツ内の要素にテキストを設定しています(⭐の部分)。具体的には、入力欄のメールアドレスを取得し、モーダル内のdiv要素のテキストとして設定しています。

✍️<template>の魅力は、いろいろな場所でコンテンツを使い回せる点です。複製コンテンツに変更を加えることで、元のコンテンツを汚さずに済みます。

実際の動作を確認してみよう

👆メールアドレスを送信すると、モーダルが表示されるのが分かると思います。


<template>を使えば、挿入するコンテンツをHTML内に保持しておけるため、うまく使えばJavaScript側での操作を少なくすることができます(たとえばcreateElementをたくさん並べる必要がなくなる等)。
大幅なDOM操作をするときにぜひ活用してみましょう。

ブラウザ対応状況

🖥デスクトップ

  • Chromeのアイコン
    Chrome
    35〜
  • Safariのアイコン
    Safari
    9〜
  • Firefoxのアイコン
    Firefox
    22〜
  • Edgeのアイコン
    Edge
    15〜
  • IEのアイコン
    IE
    未対応

📱モバイル

  • Android Chromeのアイコン
    Android Chrome
    79〜
  • iOS Safariのアイコン
    iOS Safari
    9〜

caniuse.comで詳しく見る