The Problem
Re-using HTML within the same page can be tricky. Picture this: you have a complex piece of markup that needs to appear in several places on your page.
As a web developer, you might think, "No problem, I'll just use a framework and create a component.". But does it really make sense to bring in an entire library just to re-use some HTML? Shouldn't re-using HTML be something that is supported natively?
Entering the <template>
element.
How it works
Content inside a <template>
element isn't rendered when the page loads. However, it's still part of the DOM and can be accessed via JavaScript. This lets you append this content to other DOM nodes and, thereby, making it reusable.[1]
Consider the following HTML:
<body>
<span>I'm visible.</span>
<template id="my-template">
<span>I'm initially <b>not</b> visible.</span>
</template>
</body>
As you will see below, the content from inside the <template>
is not visible. However, we can get the contents reference and append it to another node where it will be displayed:
// get the refence to the template
const template = document.getElementById('my-template');
// extract and clone the content from the template
const clonedContent = template.content.cloneNode(true);
// append the extracted content to another node
document.body.appendChild(clonedContent);
Now, the previously hidden content becomes visible. Try it out yourself:
This approach not only lets you render content dynamically, showing one component under specific conditions and another under different conditions.
It also allows you to attach the content to multiple nodes, enabling you to declare HTML once and use it multiple times across your page.
Using dynamic content
There's one more thing to consider: dynamic content.
So far, we've only defined static content in the <template>
, but what if we want to display dynamic content?
In React, you use the children
property for that. In Angular, you use <ng-content>
. With the template API, HTML introduces a native element: <slot>
.[2]
The <slot>
element specifies the entry point for child nodes. Consider this HTML:
<template>
<p>Is this the real life</p>
<slot></slot>
<p>Caught in a landslide</p>
</template>
<!-- and later -->
<bohemian-rhapsody>
<p>Is this just fantasy</p>
</bohemian-rhapsody>
The rendered result will be:
As you can see, the content put into the <bohemian-rhapsody>
element got rendered into the <slot>
element.
If you're wondering where the <bohemian-rhapsody>
element came from, check out my upcoming intro to custom elements.
Curious to dive deeper?
In my next articles on georg.dev I’ll break down the other two web component specifications as well: Shadow DOM and Custom Elements. Each article aims to equip you with the tools necessary to implement these technologies in your own projects. Keep learning!
Top comments (2)
Created, maybe. But used? YES!
Every
<input>
,<textarea>
,<video>
etc. IS a Web Component, they all have a shadowRoot.Its just that us mortal developers can't access these user-agent Web Components
Interesting thought, @dannyengelman. I googled the term "user-agent web components" and stumbled upon a few interesting StackOverflow posts of yours. Even though I noticed the shadow root on these elements at times, I never gave this too much of a thought so far. I will change the sentence to:
to make it clearer.