The template Element
Prerequisites: How the HTML parser works
A template holds markup that isn't rendered. Its content is parsed
into a separate, inert DocumentFragment: images inside don't load,
scripts don't run, and querySelector on the document doesn't find it.
JavaScript clones it when needed.
<template id="product-row">
<li class="product">
<img alt="" width="48" height="48">
<span class="name"></span>
<span class="price"></span>
</li>
</template>
<ul id="products"></ul>
<script>
const products = [
{ name: "Rye loaf", price: 4.2, img: "rye.jpg" },
{ name: "Spelt <new>", price: 3.8, img: "spelt.jpg" },
];
const tpl = document.getElementById("product-row");
const list = document.getElementById("products");
console.log("in document:", document.querySelectorAll(".product").length);
for (const p of products) {
const row = tpl.content.cloneNode(true);
row.querySelector("img").src = p.img;
row.querySelector(".name").textContent = p.name;
row.querySelector(".price").textContent = `£${p.price.toFixed(2)}`;
list.append(row);
}
console.log("in document:", document.querySelectorAll(".product").length);
console.log(list.lastElementChild.querySelector(".name").outerHTML);
</script>
in document: 0
in document: 2
<span class="name">Spelt <new></span>
tpl.contentis the fragment;cloneNode(true)makes a deep copy.- Filling the copy with
textContentkeeps user data safe. - Nothing inside the template was fetched until it was cloned into the
page — the empty
imgnever made a request.
Templates can go anywhere
The parser allows template in places where other elements can't go —
inside a table, select, or head — and parses its content as if it
were in the right context:
<table>
<tbody id="rows">
<template id="row-tpl"><tr><td class="c"></td></tr></template>
</tbody>
</table>
<script>
const row = document.getElementById("row-tpl").content.firstElementChild;
console.log(row.tagName, row.firstElementChild.tagName);
</script>
TR TD
Trying the same with a div would foster-parent the row out of the
table.
Where templates are used
- Client-side rendering without a framework.
- Web components — the next lessons.
- Declarative shadow DOM, which uses
<template shadowrootmode>. - Frameworks compile their own template syntax (Vue's
<template>, Angular, Svelte) — similar idea, different mechanism.