HTML <template> and <slot>: Reusable Markup and Content Projection

HTML template and slot are two advanced HTML features that help you build reusable interface pieces without duplicating markup. template stores inert HTML that does not render immediately, while slot lets a web component accept and place content from outside its shadow DOM.

Quick answer: Use template when you want HTML that exists in the page but does not render until you use it, and use slot when you want a web component to receive and display custom child content. They solve different problems and often work together.

Difficulty: Intermediate

You'll understand this better if you know: basic HTML structure, how attributes work, and the idea that web components can encapsulate markup.

1. What Are <template> and <slot>?

The template element is a container for HTML that the browser parses but does not display or activate right away. The slot element is used inside a web component’s shadow DOM to decide where light DOM content should appear.

These features are closely related because reusable UI patterns often use a template to define structure and slot to customize parts of that structure.

2. Why <template> and <slot> Matter

Without these elements, reusable UI often means repeating the same markup or building everything with JavaScript string manipulation. That becomes harder to maintain, easier to break, and more difficult to make accessible.

template helps you define markup once and clone it when needed. slot helps component authors expose a clean API for content like titles, buttons, icons, or descriptions while keeping structure and styling encapsulated.

They matter most when you are building:

3. Basic Syntax or Core Idea

The simplest way to think about them is:

3.1 The basic <template> structure

The browser parses the contents, but they stay hidden until something copies them into the document.

<template id="card-template">
  <article class="card">
    <h2>Card title</h2>
    <p>Card content goes here.</p>
  </article>
</template>

This markup is valid HTML, but it does not appear on the page by itself. The content becomes useful only when a script or framework clones it.

3.2 The basic <slot> structure

A slot lives inside a shadow DOM template and marks where light DOM content should be inserted.

<template id="profile-card-template">
  <article class="profile-card">
    <h2><slot>Unnamed person</slot></h2>
    <p><slot name="bio">No bio provided.</slot></p>
  </article>
</template>

Here the unnamed slot receives default children, and the named slot receives elements with a matching slot attribute.

4. Step-by-Step Examples

4.1 Cloning a template for repeated cards

This example shows the core reason template exists: you can define markup once and reuse it multiple times without copying HTML by hand.

<template id="news-card-template">
  <article class="news-card">
    <h2 class="title"></h2>
    <p class="summary"></p>
  </article>
</template>

<div id="news-feed"></div>

In a real page, a script would clone the template content, fill in the title and summary, and append it to the feed. The important HTML idea is that the template is invisible until cloned.

4.2 Using a named slot for customizable text

Named slots let component users decide exactly where special content should go.

<template id="alert-box-template">
  <article class="alert-box">
    <h2><slot name="title">Alert</slot></h2>
    <p><slot>Something happened.</slot></p>
  </article>
</template>

<my-alert>
  <span slot="title">Server error</span>
  Please try again in a few minutes.
</my-alert>

The slot="title" content goes into the named slot, while the plain text goes into the default slot.

4.3 Providing fallback content

Fallback content appears only when no matching light DOM content is provided.

<template id="dialog-template">
  <dialog open>
    <h2><slot name="heading">Default heading</slot></h2>
    <p><slot>Default dialog body.</slot></p>
  </dialog>
</template>

This fallback is helpful because your component can still render something sensible when the author forgets to supply content.

4.4 Grouping multiple slotted regions

Complex components often need more than one insertion point, such as an icon, heading, body, and actions.

<template id="panel-template">
  <section class="panel">
    <header class="panel-header">
      <slot name="icon"></slot>
      <h2><slot name="title">Panel</slot></h2>
    </header>
    <div class="panel-body">
      <slot>Panel content</slot>
    </div>
    <footer class="panel-footer">
      <slot name="actions"></slot>
    </footer>
  </section>
</template>

Multiple slots make component APIs explicit, which is often better than forcing every piece of content into one generic area.

5. Practical Use Cases

6. Common Mistakes

Mistake 1: Expecting <template> content to render automatically

A common beginner mistake is placing visible page content inside a template and expecting the browser to show it immediately.

Problem: The browser parses the markup, but template content is inert and does not appear in the document until it is cloned or otherwise inserted.

<template>
  <p>This will not appear on the page yet.</p>
</template>

Fix: Put the content outside the template if you want it visible immediately, or clone the template content into the page when needed.

<p>This appears immediately.</p>

<template>
  <p>This is stored for later reuse.</p>
</template>

The corrected version works because visible content is outside the inert template.

Mistake 2: Using the wrong slot name

If the slot attribute on the light DOM content does not match the named slot, the content falls back to the default slot or disappears from the intended location.

Problem: A name mismatch means the browser cannot associate the content with the slot you expected.

<template>
  <h2><slot name="title">Default title</slot></h2>
</template>

<my-card>
  <span slot="heading">Wrong slot name</span>
</my-card>

Fix: Make the names match exactly.

<template>
  <h2><slot name="title">Default title</slot></h2>
</template>

<my-card>
  <span slot="title">Correct slot name</span>
</my-card>

The corrected version works because the browser can now place the content into the named slot.

Mistake 3: Putting slotted content in the wrong tree

Slot assignment only works for light DOM children of the custom element, not for arbitrary elements elsewhere on the page.

Problem: Content outside the custom element cannot be projected into its slot, so the component renders fallback content instead.

<my-alert></my-alert>

<p slot="title">This is outside the component.</p>

Fix: Place the slotted element as a child of the custom element.

<my-alert>
  <p slot="title">This is inside the component.</p>
</my-alert>

The corrected version works because the slotted node is now in the right relationship to the component.

7. Best Practices

Use <template> for structure, not for hidden page content

If content should be available to users immediately, do not bury it inside a template. Reserve templates for reusable markup or inert fragments.

<template id="item-template">
  <li class="item"></li>
</template>

This keeps your document semantics clear and prevents confusion about what is visible versus reusable.

Keep slot names meaningful and minimal

Good slot names describe the role of the content, such as title, icon, or actions. Avoid making every slot a one-off name that only you can understand.

<slot name="actions"></slot>
<slot name="icon"></slot>

Clear names make component usage more predictable and easier to document.

Always provide sensible fallback content

Fallback content protects your component from looking broken when authors forget to provide optional children.

<slot name="title">Untitled</slot>

This improves resilience and accessibility because the component still has readable text.

8. Limitations and Edge Cases

9. Practical Mini Project

Here is a small but complete example of a product feature card built with a template and slots. The card supports a title, subtitle, body text, and optional actions.

<template id="feature-card-template">
  <article class="feature-card">
    <header>
      <h2><slot name="title">Untitled feature</slot></h2>
      <p class="subtitle">
        <slot name="subtitle">No subtitle provided.</slot>
      </p>
    </header>

    <div class="body">
      <slot>Feature details go here.</slot>
    </div>

    <footer class="actions">
      <slot name="actions"></slot>
    </footer>
  </article>
</template>

<feature-card>
  <span slot="title">Fast setup</span>
  <span slot="subtitle">Start in minutes</span>
  This card reuses the same internal structure while letting the page author customize the text.
  <button slot="actions">Learn more</button>
</feature-card>

This project demonstrates the full pattern: the template defines the reusable component layout, and slots expose specific regions for content authored outside the component.

10. Key Points

11. Practice Exercise

Create a reusable notification panel that supports a title slot, a default message slot, and an actions slot.

Expected output: A component-like HTML structure where the heading, body, and actions can be replaced by custom content.

Hint: Use one unnamed slot for the main message and named slots for the title and actions areas.

Solution:

<template id="notification-panel-template">
  <section class="notification-panel">
    <header>
      <h2><slot name="title">Notification</slot></h2>
    </header>
    <div class="message">
      <slot>No message provided.</slot>
    </div>
    <footer class="actions">
      <slot name="actions"></slot>
    </footer>
  </section>
</template>

This solution works because each section has a clear insertion point, and the fallback text ensures the component remains useful even when no content is provided.

12. Final Summary

template and slot solve two related but different problems. template lets you define reusable, inert HTML that you can copy into the document when needed. slot lets a web component expose locations where outside content can appear.

Together, they make component-based HTML more maintainable, more predictable, and easier to customize. If you are learning web components next, a good follow-up topic is the shadow DOM, because slots are most powerful when you understand how shadow trees and light DOM work together.

Once you can read and write templates and slots confidently, you can build cleaner custom elements, design system components, and reusable page sections without duplicating markup everywhere.