I'm looking for the most standards-compliant / future-proof method for front-end HTML templating.
There exists a relatively new W3C draft specification for HTML Templates, e.g.:
<template id="mytemplate">
<img src="" alt="great image">
<div class="comment"></div>
</template>
Does anyone know if any good JavaScript polyfills already exist to make <template>
element usable in a cross-browser way? Preferably complying with this standard.
Difficulties
According the the HTML5Rocks guide these templates have the following properties:
- "Its content is effectively inert until activated"
- "Script doesn't run, images don't load, audio doesn't play,"
- "Content is considered not to be in the document"
- "Templates can be placed anywhere inside of
<head>
,<body>
, or<frameset>
"
I think it is impossible to implement all four of these properties purely with a JavaScript polyfill, so any solution would only be partial.
Yet another possibility is Neovov's Template-Element-Polyfill.
It's a dedicated
<template>
polyfill that you can find on Github.There is a jsfiddle that demonstrates such a polyfill.
As for libraries, and I don't know that they support it yet, but try something like Modernizr and Initializr
Another possibility are the Web Components polyfills, which include a polyfill for the
<template>
tag. Keep in mind that webcomponents.js includes polyfills for more than just the<template>
tag though.Xotic750 offered a solid polyfill that works by mutating HTML elements — but it will fail if any new templates are later added to the DOM, and mutation is increasingly discouraged (where avoidable).
Instead, I recommend introducing the "polyfill" behaviour at the point where you use the templates. Add this function to your JS:
Call the function with a reference to your template element. It'll extract the content, and return a documentFragment that you can then attach to another element (or do whatever else you might want to do with the template content). Like this:
Now, the other answer didn't mention it, but you probably want some CSS to hide the
<template>
element.Here's a CodePen that puts it all together.
Now, this will work correctly in browsers that natively support the
<template>
element, and in those that don't. Similar to the other answer, it's not a perfect polyfill, since it doesn't render templates inert (that'd be complex, slow, and error-prone). But it works well enough for me to use in production.Leave a comment if you've got questions or issues, and I'll revise accordingly.