Content and templates in HTML

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

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

<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

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

We help tech communities to grow worldwide, providing top-notch tools and unparalleled networking opportunities.