DEV Community

Cover image for The <template> Tag: A core HTML Feature That Simplified My JS
Richa Parekh
Richa Parekh

Posted on

The <template> Tag: A core HTML Feature That Simplified My JS

I’m currently developing a conversational AI web application. I’ve been building it completely from scratch, following a structured SDLC approach.

Right now, I’m in Phase 3: Frontend Interactivity, where I'm working on dynamically rendering chat messages.

Initially, I took a common approach: use insertAdjacentHTML() to append user and AI message bubbles directly into the DOM. It worked, but my JavaScript file became messy with chunks of repetitive HTML.

Here’s what that looked like.

⛔ The Problem: Too Much HTML in JavaScript

<div id="messages-container"></div>
Enter fullscreen mode Exit fullscreen mode
const messagesContainer = document.getElementById('messages-container');
const messageHTML = `
  <div class="flex justify-start mb-4 animate-slide-in">
    <div class="bg-gray-100 dark:bg-gray-800 rounded-lg px-4 py-2 max-w-[70%]">
      <p class="text-gray-800 dark:text-gray-200">${text}</p>
    </div>
  </div>
`;
messagesContainer.insertAdjacentHTML('beforeend', messageHTML);
Enter fullscreen mode Exit fullscreen mode

This worked fine for a single message type, but once I needed to handle AI messages (with a different layout), I realized I was duplicating the same structure in multiple places.

It lacked simplicity. It was not scalable.
I required a method to differentiate between logic (JS) and structure (HTML) that was easier to maintain.

At that point, I discovered the <template> tag, a native feature.

✅ The Solution: <template> Tag

It allows you to define reusable HTML sections that remain inactive until you purposefully use JavaScript to render them.

In simpler terms:

  • The browser parses the HTML inside , but doesn’t display it.

  • You can clone its content with JS using template.content.cloneNode(true) whenever you need to render it dynamically.

By doing this, you can create clear, declarative HTML and then use it in your scripts without messing up your JS files with raw HTML strings.
Here’s the structure.

<template id="user-message-template">
  <div class="flex justify-start mb-4 animate-slide-in">
    <div class="bg-gray-100 dark:bg-gray-800 rounded-lg px-4 py-2 max-w-[70%]">
      <p class="text-gray-800 dark:text-gray-200 message-text"></p>
    </div>
  </div>
</template>

<div id="messages-container"></div>
Enter fullscreen mode Exit fullscreen mode

🛠️ How It Works

When the browser encounters a , it parses the markup but doesn’t render it.
This means:

  • The content inside doesn’t appear in the DOM.

  • Scripts or images inside it won’t execute or load.

  • It quietly waits to be cloned when its turn comes.

To use it, clone the content of the template by capturing it via JavaScript:

const messagesContainer = document.getElementById('messages-container');
const userTemplate = document.getElementById('user-message-template');

function addUserMessage(text) {
  // Clone the content of the template
  const messageClone = userTemplate.content.cloneNode(true);

  // Modify the cloned node
  messageClone.querySelector('.message-text').textContent = text;

  // Append it to the container
  messagesContainer.appendChild(messageClone);
}

// Example usage
const btn = document.getElementById('sendBtn');
btn.addEventListener('click', function () {
     addUserMessage('This is test user message');
});
Enter fullscreen mode Exit fullscreen mode

Your HTML is now scalable, readable, and modular.
There won't be any messy HTML duplication in my JavaScript if I decide to add an AI message later. I can just define a different template with a slightly different style.

🧐 Why is this important?

  • Cleaner: JS doesn't contain any HTML strings.

  • More maintainable: Structure can be easily changed without affecting logic.

  • Safer: Less likely to have injection problems or malformed HTML

  • Scalable: Easily adjusts to more complex message formats.

These small improvements add up in a real-world chat application, especially one that goes through several stages of development.

This structure maintains consistency and helps with debugging as the UI grows.

🔚 Conclusion

The <template> tag quietly addresses a practical issue: keeping markup and logic separate in dynamic UI.
It transformed a messy part of JavaScript into a clear, reusable system for my project.
What's the best part? There is no need for additional dependencies because it is pure JavaScript.

Sometimes, the cleanest solutions are already built into the browser. You just need to look closely.

Top comments (0)