I have been reading the documentation on the <template>
tag, and I can't seem to understand how it is different from simply using a <div>
that is display: none;
Documentation: template tag
<template>
example
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
VS
<div>
example
<div id="productrow" style="display: none">
<tr>
<td class="record"></td>
<td></td>
</tr>
</div>
PS: I am aware of browser compatibility differences
The <template> tag is used as a container to hold some HTML content hidden from the user when the page loads. The content inside <template> can be rendered later with a JavaScript.
Both the tags (<div> and <section>) are used in the webpage, <section> tag means that the content inside relates to a single theme, and <div> tag is used as a block part of the webpage and don't convey any particular meaning. HTML <div> Tag: It is called a division tag.
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.
Consider:
<template>
<style>
body: { background-color: black; }
</style>
<script>
alert('hello');
</script>
<audio src="alert.wav" autoplay></audio>
</template>
And:
<div style="display: none;">
<style>
body: { background-color: black; }
</style>
<script>
alert('hello');
</script>
<audio src="alert.wav" autoplay></audio>
</div>
Are these going to behave the same when the browser renders them? (Spoiler: no.)
To address your specific questions, though:
- On a low level, how does the browser handle these 2 examples differently?
For one, the HTML inside a <template>
does not become DOM elements that are children of the <template>
. It becomes children of an "inert" DocumentFragment (indirectly; this is a simplification) where they exist as nodes but do not "do" anything, as in the example above.
In addition to being "inert," the template contents have no "conformance requirements." Your <tr>
example above is a good one. See what happens here:
const template = document.querySelector('template');
const div = document.querySelector('div');
console.log('template.innerHTML is', template.innerHTML);
console.log('div.innerHTML is', div.innerHTML);
<template>
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
<div style="display: none">
<tr>
<td class="record"></td>
<td></td>
</tr>
</div>
In a normal document, a <tr>
can't be a child of a <div>
, so the browser just removes it. In a <template>
, that requirement doesn't exist. You would find the same with, say, <div style="{{myStyle}}">
. In a document, the browser would throw away the style
attribute because its value is invalid; in a <template>
it would not. This is what makes <template>
useful for, well, templating.
If you want to know more about how <template>
s are rendered, I suggest reading the section about it in the HTML spec. It's not easy reading, and parts may be incomprehensible, but you stand to learn a lot.
- Are certain JS methods or HTML attributes different or not available?
The <template>
element has the content
attribute, which points to the DocumentFragment discussed above.
Elements inside of <template>
can't be found by any selector in JS, so you can't accidently find them and to extract them you have to use the content
property of the HTMLTemplateElement using something like:
var clone = document.importNode(templateElement.content, true);
Also every <style>
, <audio>/<video>/...
or <script>
is parsed on page load, but doesn't run until you clone it to into the main DOM.
I found an article that explains all the differences in detail: https://www.html5rocks.com/en/tutorials/webcomponents/template/
I realize now that the <div>
example was actually, kind of a polyfill used in older browsers and has to be severely hacked to make it work as expected.
Thanks for everyone's help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With