Using the HTML <template> element
I’ve often used JavaScript to create HTML fragments that I need to repeat and populate with dynamic data.
For example, let’s say that our data is an array of objects that contain a title, description, and a path to an image that we want to iterate over and turn into a series of cards within our HTML. Here’s an example of how that data might be modeled:
let data = [
{
"title": "An Example",
"description": "This is just some example data.",
"imagePath": "/path/to/image/example.jpg"
}
...
]
Until recently, I would create these HTML fragments within JavaScript using the createElement()
method:
const createCard = (data) => {
let card = document.createElement('div');
card.classList.add('card');
let cardHeading = document.createElement('h1');
cardHeading.innerHTML = data.title;
card.appendChild(cardHeading);
let cardDescription = document.createElement('p');
cardDescription.classList.add('description');
cardDescription.innerHTML = data.description;
card.appendChild(cardHeading);
let cardImage = document.createElement('img');
cardImage.src = data.imagePath;
card.appendChild(cardImage);
return card;
}
However, I’ve now started using the <template>
HTML element to create these fragments. Here’s what that would look like within the <body>
of our HTML:
<!-- CARD TEMPLATE -->
<template id="card-template">
<div class="card">
<h1></h1>
<p class="description"></p>
<img />
</div>
</template>
These HTML fragments aren’t rendered when the page is loaded – they’re only instantiated when they’re used.
You can then use this HTML template within your JavaScript by cloning it and populating it with your data:
const createCard = (data) => {
// Get the template using the id
let cardTemplate = document.getElementById('card-template');
// Clone the template
let cardClone = template.content.cloneNode(true);
// Get the contents of the cloned template
let card = cardClone.querySelector('.card');
// Populate the contents of the cloned template with data
card.querySelector('h1').innerHTML = data.title;
card.querySelector('.description').innerHTML = data.description;
card.querySelector('img').src = data.imagePath;
return card;
}
The above, gets the card template using the id
we assigned to it, clones it, and adds some dynamic data to the elements within the cloned template.
To take this a bit further, we can abstract cloning the template into a reusable JavaScript method:
const cloneTemplate = (id) => {
let template = document.getElementById(id);
let clone = template.content.cloneNode(true);
return clone;
};
Then we can update our previous example accordingly:
const createCard = (data) => {
let cardTemplate = cloneTemplate('card-template');
let card = cardTemplate.querySelector('.card');
card.querySelector('h1').innerHTML = data.title;
card.querySelector('.description').innerHTML = data.description;
card.querySelector('img').src = data.imagePath;
return card;
}
I find this much easier to maintain than creating these HTML fragments within JavaScript directly.
Check out this example on CodePen for a fully working version of the above code.
<template>
is compatible with the latest versions of all major desktop and mobile browsers.