The HTML Content Template (<template>
) element is a mechanism for holding [[../../../../Glossary/HTML|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.
Content categories | Metadata content, flow content, phrasing content, script-supporting element |
Permitted content | No restrictions |
Tag omission | None, both the starting and ending tag are mandatory. |
Permitted parents | Any element that accepts metadata content, phrasing content, or script-supporting elements. Also allowed as a child of a <colgroup> element that does not have a span attribute.
|
Implicit ARIA role | No corresponding role |
Permitted ARIA roles | No role permitted
|
DOM interface | HTMLTemplateElement
|
Attributes
This element only includes the global attributes.
However, the HTMLTemplateElement
has a content
property, which is a read-only DocumentFragment
containing the DOM subtree which the template represents. Note that directly using the value of the content
could lead to unexpected behavior, see Avoiding DocumentFragment pitfall 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>
<!-- existing data could optionally be included here -->
</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.
// Test to see if the browser supports the HTML template element by checking // for the presence of the template element's content attribute. if ('content' in document.createElement('template')) { // Instantiate the table with the existing HTML tbody // and the row with the template var tbody = document.querySelector("tbody"); var template = document.querySelector('#productrow'); // Clone the new row and insert it into the table var clone = template.content.cloneNode(true); var td = clone.querySelectorAll("td"); td[0].textContent = "1235646565"; td[1].textContent = "Stuff"; tbody.appendChild(clone); // Clone the new row and insert it into the table var clone2 = template.content.cloneNode(true); td = clone2.querySelectorAll("td"); td[0].textContent = "0384928528"; td[1].textContent = "Acme Kidney Beans 2"; tbody.appendChild(clone2); } else { // Find another way to add the rows to the table because // the HTML template element is not supported. }
The result is the original HTML table, with two new rows appended to it via JavaScript:
table {
background: #000;
}
table td {
background: #fff;
}
Avoiding DocumentFragment pitfall
A DocumentFragment
is not a valid target for various events, as such it is often preferable to clone or refer to the elements within it.
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) {
alert("Clicked a div");
}
const firstClone = template.content.cloneNode(true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);
const secondClone = template.content.firstElementChild.cloneNode(true);
secondClone.addEventListener("click", clickHandler);
container.appendChild(secondClone);
Result
firstClone
is a DocumentFragment instance, so while it gets appended inside the container as expected, clicking on it does not trigger the click event. secondClone
is an HTMLDivElement instance, clicking on it works as one would expect.
Specifications
Specification | Status | Comment |
---|---|---|
HTML Living StandardThe definition of 'template element' in that specification. | Living Standard | |
HTML5The definition of 'template element' in that specification. | Recommendation | Initial definition |
Browser compatibility
The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
Update compatibility data on GitHub
Desktop | Mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
template
|
Chrome
Full support 26 |
Edge
Full support 13 |
Firefox
Full support 22 |
IE
No support No |
Opera
Full support 15 |
Safari
Full support 8 |
WebView Android
Full support Yes |
Chrome Android
Full support 26 |
Firefox Android
Full support 22 |
Opera Android
? |
Safari iOS
Full support 8 |
Samsung Internet Android
Full support 1.5 |
Legend
- Full support
- Full support
- No support
- No support
- Compatibility unknown
- Compatibility unknown
See also
- Web components:
<slot>
(and historical:<shadow>
) - Using templates and slots
<template>: The Content Template element by Mozilla Contributors is licensed under CC-BY-SA 2.5.