Lesson guide

Learning objectives

  • Explain the main purpose of Template element in JavaScript.
  • Identify the syntax, APIs, or concepts introduced in this lesson.
  • Use the examples to predict how JavaScript will behave before you run similar code.
  • Connect this topic to nearby lessons in Web components.

Real-world context

This lesson matters when you need to recognize where Template element fits into real JavaScript programs. A built-in element serves as a storage for HTML markup templates.

Key ideas

  • Template element is part of the Web components chapter, so it builds on the surrounding concepts rather than standing alone.
  • Read each code example in two passes: first for the result, then for the rule that explains the result.
  • When a section compares similar features, focus on the condition that makes you choose one feature over another.

Key terms

  • Template element
  • Template
  • element
  • Web components
  • JavaScript

A built-in <template> element serves as a storage for HTML markup templates. The browser ignores its contents, only checks for syntax validity, but we can access and use it in JavaScript, to create other elements.

In theory, we could create any invisible element somewhere in HTML for HTML markup storage purposes. What’s special about <template>?

First, its content can be any valid HTML, even if it normally requires a proper enclosing tag.

For example, we can put there a table row <tr>:

markup
<template>
  <tr>
    <td>Contents</td>
  </tr>
</template>

Usually, if we try to put <tr> inside, say, a <div>, the browser detects the invalid DOM structure and “fixes” it, adds <table> around. That’s not what we want. On the other hand, <template> keeps exactly what we place there.

We can put styles and scripts into <template> as well:

markup
<template>
  <style>
    p { font-weight: bold; }
  </style>
  <script>
    alert("Hello");
  </script>
</template>

The browser considers <template> content “out of the document”: styles are not applied, scripts are not executed, <video autoplay> is not run, etc.

The content becomes live (styles apply, scripts run etc) when we insert it into the document.

Inserting template

The template content is available in its content property as a DocumentFragment – a special type of DOM node.

We can treat it as any other DOM node, except one special property: when we insert it somewhere, its children are inserted instead.

For example:

markup
<template id="tmpl">
  <script>
    alert("Hello");
  </script>
  <div class="message">Hello, world!</div>
</template>

<script>
  let elem = document.createElement('div');

  // Clone the template content to reuse it multiple times
  elem.append(tmpl.content.cloneNode(true));

  document.body.append(elem);
  // Now the script from <template> runs
</script>

Let’s rewrite a Shadow DOM example from the previous chapter using <template>:

markup
<template id="tmpl">
  <style> p { font-weight: bold; } </style>
  <p id="message"></p>
</template>

<div id="elem">Click me</div>

<script>
  elem.onclick = function() {
    elem.attachShadow({mode: 'open'});

    elem.shadowRoot.append(tmpl.content.cloneNode(true)); // (*)

    elem.shadowRoot.getElementById('message').innerHTML = "Hello from the shadows!";
  };
</script>

Click me

In the line (*) when we clone and insert tmpl.content, as its DocumentFragment, its children (<style>, <p>) are inserted instead.

They form the shadow DOM:

markup
<div id="elem">
  #shadow-root
    <style> p { font-weight: bold; } </style>
    <p id="message"></p>
</div>

Common mistakes

  • Skipping the small examples and then missing the exact rule that Template element depends on.
  • Copying code without changing one value at a time to see which part controls the result.
  • Treating similar-looking syntax or APIs as interchangeable before checking their edge cases.

Summary

To summarize:

  • <template> content can be any syntactically correct HTML.
  • <template> content is considered “out of the document”, so it doesn’t affect anything.
  • We can access template.content from JavaScript, clone it to reuse in a new component.

The <template> tag is quite unique, because:

  • The browser checks HTML syntax inside it (as opposed to using a template string inside a script).
  • …But still allows use of any top-level HTML tags, even those that don’t make sense without proper wrappers (e.g. <tr>).
  • The content becomes interactive: scripts run, <video autoplay> plays etc, when inserted into the document.

The <template> element does not feature any iteration mechanisms, data binding or variable substitutions, but we can implement those on top of it.

Predict

Before running this template model, predict the five output lines. It models inert template content, valid storage of unusual top-level tags, cloning for reuse, inserting a DocumentFragment by inserting its children, and scripts becoming active only after insertion.

javascript
Reveal explanation

The template content exists but is inert while it remains in template.content, so the document starts empty and the script has not run. Inserting the cloned fragment inserts its children (style, script, tr) rather than a wrapper node. Cloning again creates separate nodes, which is why the same template can be reused for multiple component instances.

Try it

Call appendFragment(documentBody, secondClone) as well, then predict documentBody.length and script-runs. Then remove cloneContent and explain why reusing the same nodes would be a problem in a real DOM.

Practice

  • Rewrite one example from this lesson without looking at the original, then run it and compare the result.
  • Change one input, operator, method call, or option in a code sample and predict what will happen before running it.
  • Explain Template element in your own words as if you were reviewing it with another learner.

Keep learning

Continue with Shadow DOM slots, composition when you are ready for the next lesson.