<template>: The Content Template element
The <template>
HTML element is a mechanism for holding HTML that is not to be rendered immediately when a page is loaded but may be instantiated subsequently during runtime using JavaScript.
Think of a template as a content fragment that is being stored for subsequent use in the document. While the parser does process the contents of the <template>
element while loading the page, it does so only to ensure that those contents are valid; the element's contents are not rendered, however.
Attributes
The only standard attributes that the <template>
element supports are the global attributes.
In Chromium-based browsers, the <template>
element also supports a non-standard shadowrootmode
attribute, as part of an experimental "Declarative Shadow DOM" proposal. In supporting browsers, a <template>
element with the shadowrootmode
attribute is detected by the HTML parser and immediately applied as the shadow root of its parent element. shadowrootmode
can take a value of open
or closed
; these are equivalent to the open
and closed
values of the Element.attachShadow()
mode
option.
Also, the corresponding HTMLTemplateElement
interface includes a standard content
property (without an equivalent content/markup attribute). This content
property is read-only and holds a DocumentFragment
that contains the DOM subtree represented by the template. Be careful when using the content
property because the returned DocumentFragment
can exhibit unexpected behavior. For more details, see the Avoiding DocumentFragment pitfalls section below.
Examples
First we start with the HTML portion of the example.
<table id="producttable">
<thead>
<tr>
<td>UPC_Code</td>
<td>Product_Name</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
First, we have a table into which we will later insert content using JavaScript code. Then comes the template, which describes the structure of an HTML fragment representing a single table row.
Now that the table has been created and the template defined, we use JavaScript to insert rows into the table, with each row being constructed using the template as its basis.
if ("content" in document.createElement("template")) {
const tbody = document.querySelector("tbody");
const template = document.querySelector("#productrow");
const clone = template.content.cloneNode(true);
let td = clone.querySelectorAll("td");
td[0].textContent = "1235646565";
td[1].textContent = "Stuff";
tbody.appendChild(clone);
const clone2 = template.content.cloneNode(true);
td = clone2.querySelectorAll("td");
td[0].textContent = "0384928528";
td[1].textContent = "Acme Kidney Beans 2";
tbody.appendChild(clone2);
} else {
}
The result is the original HTML table, with two new rows appended to it via JavaScript:
Avoiding DocumentFragment pitfalls
When a DocumentFragment
value is passed, Node.appendChild
and similar methods move only the child nodes of that value into the target node. Therefore, it is usually preferable to attach event handlers to the children of a DocumentFragment
, rather than to the DocumentFragment
itself.
Consider the following HTML and JavaScript:
HTML
<div id="container"></div>
<template id="template">
<div>Click me</div>
</template>
JavaScript
const container = document.getElementById("container");
const template = document.getElementById("template");
function clickHandler(event) {
event.target.append(" — Clicked this div");
}
const firstClone = template.content.cloneNode(true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);
const secondClone = template.content.cloneNode(true);
secondClone.children[0].addEventListener("click", clickHandler);
container.appendChild(secondClone);
Result
Since firstClone
is a DocumentFragment
, only its children are added to container
when appendChild
is called; the event handlers of firstClone
are not copied. In contrast, because an event handler is added to the first child node of secondClone
, the event handler is copied when appendChild
is called, and clicking on it works as one would expect.
Technical summary
Specifications
Browser compatibility
|
Desktop |
Mobile |
|
Chrome |
Edge |
Firefox |
Internet Explorer |
Opera |
Safari |
WebView Android |
Chrome Android |
Firefox for Android |
Opera Android |
Safari on IOS |
Samsung Internet |
template |
26 |
13 |
22 |
No |
15 |
8 |
Yes |
26 |
22 |
14 |
8 |
1.5 |
shadowrootmode |
11190–111 |
11190–111 |
No |
No |
9776–97 |
16.4 |
11190–111 |
11190–111 |
No |
64 |
16.4 |
22.015.0–22.0 |
See also