Learn how to create your HTML template by using the native element and dynamically build structured content in your Web pages.

Creating HTML templates in the context of Web programming is a very common task both on the server and on the client side. Traditionally, on the client side, this task is assigned to libraries like handlebars or mustache and similar. These libraries defined a sort of standard in frontend programming. Still, their internal behavior requires string interpolation, DOM building and rendering, and related work that you can avoid with a native approach to templating.

In fact, for a few years, HTML specifications introduced a native way to create templates on the client side based on the <template> element. However, this native approach seems to be not well known among frontend developers. Let’s take a look at it in order to understand how to use it and which benefits it brings to the table.

Detecting template support

Although most recent browsers widely support the <template> element, it is always a good practice to detect if the current browser is supporting it. The typical approach is to create an instance of the element via DOM APIs and check if the content property is available, as shown by the following code:

if ('content' in document.createElement('template')) {

//...

}

If the <template> element is not supported, you can use the templating library you prefer as a fallback.

Declaring a template

The <template> element allows us to declare a template, that is a structure of HTML tags we will fill at runtime with actual values. Defining a template is very easy. All you have to do is add a <template> element in the head or in the body of your HTML page and put some HTML inside the starting and the ending tags. The following is an example of template:

<template id="bookDetailTemplate">

<li>

<img src="">

<h5></h5>

<p></p>

</li>

</template>

This example defines a list item as the template for the markup describing a book. The details of the book description consist of an image (<img>), a title (<h5>), and a text (<p>). Notice that we assigned an id to the template: bookDetailTemplate. This id is needed to identify the template when we will use it at runtime.

You can put the template element in the head section or in the body of the HTML page, at your convenience. In addition, the template element can contain any valid HTML markup, including <style> and <script> elements, and even the <template> element itself. However, the markup don’t need to represent a complete and working item. For instance, the template we defined above is not a complete list, but just a list item. Also, the image and the other elements inside the template are not defined. Their value will be assigned at runtime, when the template will become a living branch of the DOM tree.

The main feature of the <template> element is its inertness. In fact, its content is hidden until the template is not activated. Any content inside it is not loaded, nor rendered, nor executed. This means that, for example, any image contained in a template is not loaded, and any script is not executed when the template’s content is parsed. The browser only checks the markup validity and creates a hidden DOM for it until the template is not used. All this stuff will become active only when the template will be used. But how it happens?

Using a template

Once a template is declared, you can use it with JavaScript in a few simple steps. First of all, you need to access the <template> element through the classic getElementById() method, as shown below:

const bookDetailTemplate = document.getElementById("bookDetailTemplate").content;

In this example, we actually get the internal content of the <template> element identified by the bookDetailTemplate id. The content property provides the inert DOM structure generated by the markup inside the <template> element.

Once you get access to the template’s content, you can manipulate its DOM structure like the standard DOM. For example, you can access the image in our template with the following code:

const img = bookDetailTemplate.querySelector("img");

img.src = "images/myImage.jpg";

However, all this stuff comes to life only when the template’s content is appended to the page’s DOM, as in the following example:

const bookList = document.getElementById("bookList");

bookList.appendChild(bookDetailTemplate.cloneNode(true));

Looking at the code above, you’re surely be wondering why we have cloned the template’s content before appending it to the DOM. The answer is pretty simple. Since you created a template, very likely, you would create multiple instances of DOM portions from it. But if you don’t clone the piece you are adding to the DOM, your manipulations will affect all the other instances you’ve already added. So, this step is fundamental.

To illustrate a complete example of template use at runtime, consider the following code:

const bookData = [

{

cover: "...",

title: "...",

text: "..."

},

...

];

const bookDetailTemplate = document.getElementById("bookDetailTemplate").content;

const bookList = document.getElementById("bookList");



for (let bookDetail of bookData) {

const img = bookDetailTemplate.querySelector("img");

img.src = bookDetail.cover;



const title = bookDetailTemplate.querySelector("h5");

title.innerText = bookDetail.title;



const text = bookDetailTemplate.querySelector("p");

text.innerHTML = bookDetail.text;



bookList.appendChild(bookDetailTemplate.cloneNode(true));

}

In this example, we are mapping an array of objects, bookData, to the DOM by using the template declared before. Notice how we are creating an instance of a list item for each object using the template.

Summary

As you’ve seen in this article, creating and using an HTML template via the native <template> element is straightforward. The declaration and use of the template are not so different from the approach proposed by most common templating libraries. However, the native <template> element provides you with a few benefits. It allows you to leverage the native templating engine supported by most recent browsers with noticeable performance gain. In addition, it frees you from third parties libraries dependency.