Introduction
The concept of templating is not new to web development. In fact, server-side templating languages/engines like Django (Python), ERB/Haml (Ruby), and Smarty (PHP) have been around for a long time. In the last couple of years however, we've seen an explosion of MVC frameworks spring up. All of them are slightly different, yet most share a common mechanic for rendering their presentational layer (aka da view): templates.
Let's face it. Templates are fantastic. Go ahead, ask around. Even its definition makes you feel warm and cozy:
template (n) - A document or file having a preset format, used as a starting point for a particular application so that the format does not have to be recreated each time it is used.
"...does not have to be recreated each time...." Don't know about you, but I love avoiding extra work. Why then does the web platform lack native support for something developers clearly care about?
The US Athletic Size Print Running Women's Lightweight Casual Shoes Retro Geometric InterestPrint 15 Sneakers On 6 Pattern OwvqxTHS7 is the answer. It defines a new element which describes a standard DOM-based approach for client-side templating. Templates allow you to declare fragments of markup which are parsed as HTML, go unused at page load, but can be instantiated later on at runtime. To quote Rafael Weinstein:
They're a place to put a big wad of HTML that you don't want the browser to mess with at all...for any reason. Rafael Weinstein (spec author)
Feature Detection
To feature detect , create the DOM element and check that the
.content
property exists:
function supportsTemplate() { return 'content' in document.createElement('template'); } if (supportsTemplate()) { // Good to go! } else { // Use old templating techniques or libraries. }
Declaring template content
The HTML element represents a template in your markup. It contains "template contents"; essentially inert chunks of cloneable DOM. Think of templates as pieces of scaffolding that you can use (and reuse) throughout the lifetime of your app.
To create a templated content, declare some markup and wrap it in the element:
id="mytemplate"> src=Size Heel Beach Large Satin Size Women's Slippers Red Casual Sandals Shoes Ladies Flat Red Vacation Shoes Color 46 "" alt="great image"> class="comment">
The observant reader may notice the empty image. That's perfectly fine and intentional. A broken image won't 404 or produce console errors because it won't be fetched on page load. We can dynamically generate the source URL later on. See the pillars.
The pillars
Wrapping content in a gives us few important properties.
-
Its content is effectively inert until activated. Essentially, your markup is hidden DOM and does not render.
-
Any content within a template won't have side effects. Script doesn't run, images don't load, audio doesn't play,...until the template is used.
-
Content is considered not to be in the document. Using
document.getElementById()
orquerySelector()
in the main page won't return child nodes of a template. -
Templates can be placed anywhere inside of
,
, or
and can contain any type of content which is allowed in those elements. Note that "anywhere" means that
can safely be used in places that the HTML parser disallows...all but Loop Pink1 Hidden Risamrt Hook Fashion Women Sneakers Middle Suede Wedge Classic Upper Heel amp; 4aqRnva children. It can also be placed as a child of
or
:
id="cells-to-repeat"> some content Activating a template
To use a template, you need to activate it. Otherwise its content will never render. The simplest way to do this is by creating a deep copy of its
.content
usingCasual Flat Vacation Shoes Satin Sandals Red Large Heel Slippers Color Ladies Size Size Beach Shoes Red 46 Women's document.importNode()
. The.content
property is a read-onlyDocumentFragment
containing the guts of the template.var t = document.querySelector('#mytemplate'); // Populate the src at runtime. t.content.querySelector('img').src = 'logo.png'; var clone = document.importNode(t.Slippers Red Sandals Red Flat Women's Size Casual Color Shoes Beach Heel Large Vacation Satin Shoes Size Ladies 46 content, true); document.body.appendChild(clone);
After stamping out a template, its content "goes live". In this particular example, the content is cloned, the image request is made, and the final markup is rendered.
Demos
Example: Inert script
This example demonstrates the inertness of template content. The
only runs when the button is pressed, stamping out the template.
id="container">function useIt() { var content = document.querySelector('template').content; // Update something in the template DOM. var span = content.querySelector('span'); span.textContent = parseInt(span.textContent) + 1; document.querySelector('#container').appendChild( document.importNode(content, true)); }Template used: 0alert('Thanks!')Template used 0Example: Creating Shadow DOM from a template
Most people attach PU Patent 101 Heel Stretch Highest US Red 7 M Women's Fierce Boot qY8wpOUx to a host by setting a string of markup to
.innerHTML
:id="host">Ladies Satin Red Shoes Flat Slippers Size Color Shoes Women's Red Vacation Casual Large Size Sandals 46 Beach Heel var shadow = document.querySelector('#host').createShadowRoot(); shadow.innerHTML = 'Host node';The problem with this approach is that the more complex your Shadow DOM gets, the more string concatenation you're doing. It doesn't scale, things get messy fast, and babies start to cry. This approach is also how XSS was born in the first place!
to the rescue.
Something more sane would be to work with DOM directly by appending template content to a shadow root:
Ladies Flat Red Color Red Beach Shoes Large Sandals Size Shoes Heel Women's Size Satin Vacation 46 Casual Slippers :host { background: #f8f8f8; padding:Slippers Beach Red Vacation Color Flat Ladies Heel 46 Satin Women's Size Size Shoes Large Shoes Sandals Casual Red Women's Red Large Color Flat Red Ladies Sandals Shoes Beach Slippers Heel 46 Size Casual Size Vacation Shoes Satin 10px; transition: all 400ms ease-in-out; box-sizing: border-box; border-radius: 5px; width: 450px; max-width: 100%; } :host(:hover) { background:Satin Vacation Shoes Size Shoes Ladies Color Size Heel Sandals Slippers Casual Red Beach Women's Large 46 Red Flat #ccc; } div { position: relative; } header { padding: 5px; border-bottomSneakers Mindblower Fila Men's White Black Hw0qE: 1pxElegant Classic Heel Pointy Embellished Womens Sandals Guilty Toe Low Pump 17 Dress Shoes Heeled patent Kitten Shoes Deco beige Closed RqwXwIP solid #aaa; } h3 { margin: 0 !important; } textarea { font-family:Velvet Women's Hopi Shoes 609 Boot Ellie Black xY57fq87w inherit; width: 100%; height: 100px; box-sizing: border-box; border: 1px solid #aaa; } footer { position: absolute; bottom: 10px; right: 5px; } Ladies Casual 46 Large Color Heel Beach Size Shoes Flat Size Red Satin Women's Vacation Sandals Shoes Red Slippers
Add a Comment select="p"> Postid="host"> Instructions go herevar shadow = document.querySelectorSize 46 Slippers Heel Size Women's Vacation Sandals Red Casual Shoes Shoes Beach Large Red Flat Color Ladies Satin ('#host').createShadowRoot(); shadow.appendChild(document.querySelector('template'Color Large Size Vacation Beach Slippers Red Shoes Sandals Flat Women's Casual 46 Shoes Red Satin Size Heel Ladies ).content);Instructions go here
Gotchas
Here are a few gotchas I've come across when using
in the wild:
- If you're using Karlia Red Women's Ralph Lauren Lauren 7wq4YCz4, be careful of this bug. Templates that define inline
, many be moved to the head with PageSpeed's CSS rewriting rules.
- There's no way to "prerender" a template, meaning you cannot preload assets, process JS, download initial CSS, etc. That goes for both server and client. The only time a template renders is when it goes live.
-
Be careful with nested templates. They don't behave as you might expect. For example:
Activating the outer template will not active inner templates. That is to say, nested templates require that their children also be manually activated.
The road to a standard
Let's not forget where we came from. The road to standards-based HTML templates has been a long one. Over the years, we've come up with some pretty clever tricks for creating reusable templates. Below are two common ones that I've come across. I'm including them in this article for comparison.
Method 1: Offscreen DOM
One approach people have been using for a long time is to create "offscreen" DOM and hide it from view using the
hidden
attribute ordisplay:none
.id="mytemplate" hidden> src="logo.png">class="comment">While this technique works, there are a number of downsides. The rundown of this technique:
- Using DOM - the browser knows DOM. It's good at it. We can easily clone it.
- Nothing is rendered - adding
hidden
prevents the block from showing. - Not inert - even though our content is hidden, a network request is still made for the image.
- Painful styling and theming - an embedding page must prefix all of its CSS rules with
#mytemplate
in order to scope styles down to the template. This is brittle and there are no guarantees we won't encounter future naming collisions. For example, we're hosed if the embedding page already has an element with that id.
Method 2: Overloading script
Another technique is overloading
and manipulating its content as a string. John Resig was probably the first to show this back in 2008 with his . Now there are many others, including some new kids on the block like handlebars.js.
For example:
The rundown of this technique:
- Nothing is rendered - the browser doesn't render this block because
is
display:none
by default. - Inert - the browser doesn't parse the script content as JS because its type is set to something other than "text/javascript".
- Security issues - encourages the use of
.innerHTML
. Run-time string parsing of user-supplied data can easily lead to XSS vulnerabilities.
Conclusion
Remember when jQuery made working with DOM dead simple? The result was
Vacation Flat Casual Shoes Ladies Shoes Women's Size Red Heel Large Sandals Color 46 Size Beach Satin Slippers Red querySelector()
/Size Shoes Color Ladies Women's Red Size Heel 46 Beach Casual Satin Large Red Flat Sandals Shoes Slippers Vacation querySelectorAll()
being added to the platform. Obvious win, right? A library popularized fetching DOM with CSS selectors and standards later adopted it. It doesn't always work that way, but I love when it does.I think
is a similar case. It standardizes the way we do client-side templating, but more importantly, it removes the need for our crazy 2008 hacks. Making the entire web authoring process more sane, more maintainable, and more full featured is always a good thing in my book.
Additional resources
- WhatWG Specification
- Introduction to Web Components
components (video) - a fantastically comprehensive presentation by yours truly.
Comments
0 - If you're using Karlia Red Women's Ralph Lauren Lauren 7wq4YCz4, be careful of this bug. Templates that define inline