The HTML5 template element is a tag that isn’t used that much but is very useful to prepare reusable HTML structures that can be instantiated and populated with JavaScript. The DOM API and JavaScript don’t offer any native data binding. Though with the template element we can implement a kind of one time data binding easily and without any external library.

The template tag

A <template> tag isn’t displayed by default. This is basically an HTML snippet prepared in the document. In this example the template is a table row with three columns:

<template id="color-template">
        <td class="color-name"></td>
        <td class="color-value"></td>
        <td class="color-sample"></td>

Then in the document I’m adding a table with three columns. The <tbody> is empty for now. It will contain the instances of the template.

<table class="colors-table">
            <th>Color name</th>
        <!-- Will be populated -->

Instantiate the template

Here I’m setting up a very basic JSON data sample object. In real life it could be the result of an XMLHttpRequest from an API for example. In this example the keys are all the names of the gray color keywords in CSS and the values are their hexadecimal string representation.

const colorsData = {
    "black":          "#000000",
    "darkslategray":  "#2f4f4f",
    "dimgray":        "#696969",
    "gray":           "#808080",
    "slategray":      "#708090",
    "lightslategray": "#778899",
    "darkgray":       "#a9a9a9",
    "silver":         "#c0c0c0",
    "lightgray":      "#d3d3d3",
    "gainsboro":      "#dcdcdc",
    "whitesmoke":     "#f5f5f5",
    "ghostwhite":     "#f8f8ff",
    "snow":           "#fffafa",
    "white":          "#ffffff"

Then we can prepare a few other variables. I’m using ES6 constants here as I won’t modifiy the values.

const colorTemplate = document.getElementById("color-template"),
      colorsTable = document.querySelector(".colors-table"),
      colorsTableBody = colorsTable.querySelector("tbody");

Then to populate the instance of the template a loop is run on the keys of the sample object:

for (let colorName in colorsData) {
    const colorValue = colorsData[colorName],
          colorTemplateInstance = document.importNode(colorTemplate.content, true);
    colorTemplateInstance.querySelector(".color-name").textContent = colorName;
    colorTemplateInstance.querySelector(".color-value").textContent = colorValue;
    colorTemplateInstance.querySelector(".color-sample").style.background = colorValue;

Full example

Using the template element

The important part is to clone the content of the template by importing its elements:

let templateInstance = document.importNode(template.content, true);

The second parameter is to import all the descendants when set to true. This is of course what we want! The instance of the template isn’t displayed yet but we can already work on its DOM structure by modifying classes or adding content for example. For now the modifications are done in memory only and at this point the link to the initial template is lost.

Then to display the instance of the template we must add it somewhere in the current document.


Or another possibility:

parentElement.insertBefore(templateInstance, siblingElement);

This is very similar to importing nodes from an <iframe>. The documentation pages about these functions of the DOM API:

Browser support

Browser support is quite good according to Can I use. For this article I’ve written ES6 JavaScript code since browser support for HTML templates and the few ES6 features I’ve used is quite equivalent.


A full demo using a template that contains both HTML and SVG elements. This example displays random colors in the hue, saturation and lightness HSL model.