Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a browser handle a <template> tag VS a <div> tag

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>
  1. On a low level, how does the browser handle these 2 examples differently?
  2. Are certain JS methods or HTML attributes different or not available?

PS: I am aware of browser compatibility differences

like image 608
PrivatMamtora Avatar asked Apr 25 '18 18:04

PrivatMamtora


People also ask

What is the template tag used for?

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.

What is difference between div and section tag in HTML?

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.

How do HTML templates work?

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.


3 Answers

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:

  1. 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.

  1. 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.

like image 143
Jordan Running Avatar answered Nov 12 '22 20:11

Jordan Running


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.

like image 33
Sebastian Speitel Avatar answered Nov 12 '22 20:11

Sebastian Speitel


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.

like image 39
PrivatMamtora Avatar answered Nov 12 '22 20:11

PrivatMamtora