Sign in
Topics
Use prompts to convert designs into responsive HTML blocks
Where should custom content go in your component? Learn how the slot tag helps structure content in shadow DOM without losing control. Get practical tips and examples to build cleaner HTML components.
Building reusable web components often sounds simple—until you need to control where custom content should appear. Content placement inside a shadow DOM can get messy quickly without the right approach. That’s where the slot tag comes in.
Why is content insertion such a challenge in component-based design?
The slot element gives you a structured way to display user-provided content without breaking encapsulation.
In this article, you’ll learn how it works, how to use it in real-world templates, and how to style slotted elements precisely. We’ll cover its syntax, behavior, and practical use cases with clear examples and diagrams.
If you want to improve your understanding of HTML components and the shadow DOM, this walkthrough will help you build confidently.
The slot tag is an HTML element used in web components to define placeholders for external content projected into a component’s shadow DOM. It's a pseudo-element allowing developers to control where content appears, even using separate DOM trees.
By default, when you create a shadow root, content placed inside the custom element won't show unless explicitly routed through a slot.
1<custom-card> 2 <h3 slot="title">Article Title</h3> 3 <p slot="body">This is the body content.</p> 4</custom-card> 5
The inner content here is routed to the shadow DOM’s named slot using the slot attribute.
Here's how you might build a simple custom element that uses slots:
1<template id="card-template"> 2 <style> 3 .card { 4 border: 1px solid #ddd; 5 padding-left: 16px; 6 font-family: sans-serif; 7 font-size: 16px; 8 border-radius: 4px; 9 box-shadow: 0 2px 5px rgba(0,0,0,0.1); 10 } 11 ::slotted(h3) { 12 font-weight: bold; 13 font-size: 20px; 14 } 15 </style> 16 <div class="card"> 17 <slot name="title"></slot> 18 <slot name="body"></slot> 19 </div> 20</template> 21
1class CustomCard extends HTMLElement { 2 constructor() { 3 super(); 4 const shadow = this.attachShadow({ mode: 'open' }); 5 const template = document.getElementById('card-template'); 6 const content = template.content.cloneNode(true); 7 shadow.appendChild(content); 8 } 9} 10 11customElements.define('custom-card', CustomCard); 12
The class extends the HTMLElement approach to define the custom element. The template is cloned into the shadow root, forming a new shadow tree with light DOM content projected into the slot elements.
Named slots are declared using the name attribute:
1<slot name="title"></slot> 2
To project content, use the slot attribute on elements inside the light DOM:
1<h3 slot="title">Blog Title</h3> 2
A default slot is used when no name attribute is provided. It's the fallback for any content without a specified slot name.
1<slot></slot> 2
If no content is passed into a slot, you can specify fallback content:
1<slot name="footer">No footer provided</slot> 2
This improves web page UX by displaying useful placeholder content.
When using web components, the light DOM (where the consumer places their content) is separate from the shadow DOM, which defines internal layout and styles. This creates separate DOM trees, allowing style encapsulation and markup control.
Explanation: The user writes markup inside the custom element, which becomes the slot’s content. The slot element then routes this to the component's shadow DOM tree.
To apply CSS styles to content passed through slots, use the ::slotted pseudo-element.
1::slotted(h3) { 2 color: #333; 3 font-weight: bold; 4} 5
This allows font weight bold or font family sans-serif to be applied while maintaining encapsulation. Keep in mind:
Using the template element, we can declare fragments of reusable HTML, then clone and insert them dynamically.
1<template id="message-template"> 2 <div class="message"> 3 <slot name="message"></slot> 4 </div> 5</template> 6
In JavaScript, clone the template content:
const template = document.getElementById('message-template');
const content = template.content.cloneNode(true);
shadow.appendChild(content);
Slot element lets you inject different messages into the same structure using different slot names.
Sometimes developers use a span slot or div class combinations to maintain the layout:
1<div class="header"> 2 <span slot="title">My Title</span> 3</div> 4
This is useful for adding a placeholder inside a web component, controlling layout and padding left or border left while still using flexible template content.
1<template id="tooltip-template"> 2 <style> 3 .tooltip { 4 position: relative; 5 display: inline-block; 6 } 7 .tooltip-text { 8 visibility: hidden; 9 background-color: black; 10 color: white; 11 font-family: sans-serif; 12 font-size: 14px; 13 font-weight: bold; 14 padding: 5px 10px; 15 border-radius: 4px; 16 position: absolute; 17 top: 100%; 18 left: 50%; 19 transform: translateX(-50%); 20 } 21 .tooltip:hover .tooltip-text { 22 visibility: visible; 23 } 24 </style> 25 <div class="tooltip"> 26 <slot></slot> 27 <div class="tooltip-text"> 28 <slot name="tooltip-text">Default tooltip</slot> 29 </div> 30 </div> 31</template> 32
1class CustomTooltip extends HTMLElement { 2 constructor() { 3 super(); 4 const shadow = this.attachShadow({ mode: 'open' }); 5 const template = document.getElementById('tooltip-template'); 6 const content = template.content.cloneNode(true); 7 shadow.appendChild(content); 8 } 9} 10 11customElements.define('custom-tooltip', CustomTooltip); 12
Use the component as:
1<custom-tooltip> 2 <span>Hover me</span> 3 <span slot="tooltip-text">This is the tooltip info</span> 4</custom-tooltip> 5
Concept | Description |
---|---|
slot | Placeholder inside shadow DOM for projecting content |
slot attribute | Assigns light DOM content to named slot |
default slot | Renders unmatched content if no name is given |
shadow tree | Structure inside the shadow DOM |
template content | HTML fragments declared for reuse |
::slotted() | CSS pseudo-element to style slotted content |
fallback content | The default display when no slot content is passed |
The slot tag helps you insert flexible content into web components without losing structure or clarity. Named and default slots let you control layout while keeping encapsulation intact. Combined with shadow DOM, they make your components cleaner and easier to reuse.
As projects grow, you’ll need modular UI building blocks that support custom content. Start applying these techniques to create components that last, adapt, and perform well.