• Crafting Reusable HTML Templates
  • Originally written by Caleb Williams
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: Mirosalva
  • Proofread by: Xionglong58, HearFishle

In our last article, we discussed the advanced features of the Web component specification (custom elements, Shadow DOM, and HTML templates). In this and the next three articles, we’ll put these techniques to the test and verify them in more detail to see how we can apply them in today’s products. To do this, we’ll build a custom schema dialog box from scratch to see how these different technologies fit together.

Series of articles:

  1. Introduction to Web Components
  2. Write reusable HTML templates (In this paper,)
  3. Create custom elements from 0
  4. Use Shadow DOM to encapsulate style and structure
  5. Advanced tools for Web components

HTML template

One of the least recognized but most powerful features in the Web component specification is the < template > element. In the first article in this series, we defined this template element as a “user-defined HTML template that is rendered only when called.” In other words, a template is HTML code that is executed only when the browser is told, and otherwise ignored.

Such modules can be delivered and applied in many interesting ways. For the purpose of this article, we’ll look at how to create a template for a dialog box that will eventually be used in a custom element.

Define your template

As simple as it sounds, a

<template>
  <h1>Hello world</h1>
</template>
Copy the code

Running this code in a browser displays a blank page because the browser has not rendered the template element content. The power of this approach is that it allows us to save our custom content (or content structure) for later use without having to use JavaScript to write HTML code on the fly.

To use the template, we’ll need JavaScript.

const template = document.querySelector('template');
const node = document.importNode(template.content, true);
document.body.appendChild(node);
Copy the code

The real magic is in the document.importNode method. This function creates a copy of the contents of the template and is ready to insert the copy into other documents (or document fragments). The first argument to the function retrieves the contents of the template, and the second argument tells the browser to make a deep copy of the element’s DOM subtree (that is, all of its children).

We can use template.content directly, but to do so, we then need to remove the content from the element and concatenate it into the body of another document. Any DOM node can be plugged into only one location, so subsequent use of template content will result in an empty document fragment (essentially a null value) because the content object has been moved. Using document.importNode allows us to reuse instances of the same template content in different locations.

After the above code is executed, the node content is spliced into the Document.body object and rendered for display to the user. This eventually enabled us to do a lot of interesting things, such as providing templates for our users (or consumers of our application) to create content, similar to the demo below, which we discussed in the first article:

See a sample note template, Caleb Williams (@calebdWilliams) from CodePen.

In this example, we provide two templates to render the same content — the author and his book. When the table changes, we choose to render the template associated with that change value. Using the same technique allows us to eventually create a custom element that will use the template defined later.

The versatility of templates

One interesting point about templates is that we can include any HTML, including scripts and style elements. A very simple example of a template is to add a button that prompts you to click.

<button id="click-me">Log click event</button>
Copy the code

Let’s add styles:

button {
  all: unset; background: tomato; border: 0; border-radius: 4px; color: white; font-family: Helvetica; The font - size: 1.5 rem; padding: .5rem 1rem; }Copy the code

. Then call the button with a very simple script:

const button = document.getElementById('click-me');
button.addEventListener('click', event => alert(event));
Copy the code

Of course, we can use the

<template id="template">
  <script>
    const button = document.getElementById('click-me');
    button.addEventListener('click', event => alert(event));
  </script>
  <style>
    #click-me {
      all: unset; background: tomato; border: 0; border-radius: 4px; color: white; font-family: Helvetica; The font - size: 1.5 rem; padding: .5rem 1rem; } </style> <button id="click-me">Log click event</button>
</template>
Copy the code

Once the element is added to the DOM structure, we see a new button with ID #click-me, a global CSS selector bound to the button’s ID, and a simple event-listening callback that prompts the element’s click event.

For our script, we only need to concatenate the content using document.importNode, and we have an HTML template that contains the rough content and can be reused from page to page.

See notes containing template examples of scripts and styles from Caleb Williams of CodePen (@calebdWilliams).

Write the template for our dialog

Back to the task of writing a dialog element, we want to define our own template content and style.

<template id="one-dialog">
  <script>
    document.getElementById('launch-dialog').addEventListener('click', () => {
      const wrapper = document.querySelector('.wrapper');
      const closeButton = document.querySelector('button.close');
      const wasFocused = document.activeElement;
      wrapper.classList.add('open');
      closeButton.focus();
      closeButton.addEventListener('click', () => {
        wrapper.classList.remove('open'); wasFocused.focus(); }); }); </script> <style> .wrapper { opacity: 0; Transition: opacity, 0.25s ease-in; } .wrapper:not(.open) { visibility: hidden; } .wrapper.open { align-items: center; display: flex; justify-content: center; height: 100vh; position: fixed; top: 0; left: 0; right: 0; bottom: 0; opacity: 1; visibility: visible; }. Overlay {background: rgba(0, 0, 0, 0.8); height: 100%; position: fixed; top: 0; right: 0; bottom: 0; left: 0; width: 100%; } .dialog { background:#ffffff;
      max-width: 600px;
      padding: 1rem;
      position: fixed;
    }
    button {
      all: unset; cursor: pointer; The font - size: 1.25 rem; position: absolute; top: 1rem; right: 1rem; } button:focus { border: 2px solid blue; } </style> <div class="wrapper">
  <div class="overlay"></div>
    <div class="dialog" role="dialog" aria-labelledby="title" aria-describedby="content">
      <button class="close" aria-label="Close"> &#x2716; ️ 
      <h1 id="title">Hello world</h1>
      <div id="content" class="content">
        <p>This is content in the body of our modal</p>
      </div>
    </div>
  </div>
</template>
Copy the code

This code will form the basis of our dialog. To recap, we have a global close button, a title and some content. We have also added some behavior to the visual trigger dialog (although it is not yet accessible). Unfortunately, styles and script content were not limited to our template, but to the entire file, and when we added multiple template instances to the DOM, it didn’t produce the desired effect. In the next article, we’ll apply the custom element F generation method and create our own elements, using the template in real time and encapsulating the behavior of the elements.

Check out notes to script the template dialog from Caleb Williams of CodePen (@calebdWilliams).

Article Series:

  1. Introduction of Web Components
  2. Write reusable HTML templates (In this paper,)
  3. Create custom elements from 0
  4. Use Shadow DOM to encapsulate style and structure
  5. Advanced tools for Web components

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.