A product card component needs to accept a different title each time it is used, a different image, sometimes an extra button. Hard coding that component with an attribute for every variant quickly becomes unmanageable as soon as the internal structure grows more complex. Web Components solve this with an encapsulated internal DOM, but they still need a mechanism to let outside content slip into specific spots inside it.
The <slot> tag is that mechanism: a reserved spot inside a component's DOM, where content supplied from the outside gets inserted.
Definition
<slot> marks, inside the shadow DOM of a custom element, the exact place where content placed by whoever uses the component should appear. The component defines its internal structure, and delegates certain spots within that structure to whoever uses it, somewhat like a letter template leaves blank spaces to fill in.
Without an active shadow DOM, <slot> performs no distribution role at all: it is not a general layout tag, its mechanism only makes sense within the specific context of custom elements. That does not make it invisible, though: left on its own, it simply displays its own content, like any other element.
Named slots with the name attribute
A simple component only needs a single default slot, with no name. As soon as it needs to host several distinct content areas, each <slot> gets a name attribute, and the content meant for it carries a matching slot attribute with the same value.
| Element | Role |
|---|---|
<slot> with no name | Receives all content with no explicit slot attribute |
<slot name="title"> | Reserves a spot named title |
An element with slot="title" | Lands in the slot named title, wherever it appears in the HTML |
Concrete example
Here is the minimal definition of a card, with two named slots for the title and the image, plus a default slot for the description.
<template id="product-card">
<div class="card">
<slot name="title">Default title</slot>
<slot name="image"></slot>
<slot>No description provided</slot>
</div>
</template>
<product-card>
<h2 slot="title">Wireless headphones</h2>
<img slot="image" src="headphones.jpg" alt="Black headphones">
<p>30 hours of battery life.</p>
</product-card>The description paragraph has no slot attribute, so it lands in the unnamed default slot. The fallback content written inside each <slot>, like Default title, only shows up if nobody supplies content for that spot.
Pairing with <template>
<template> and <slot> almost always work together inside a custom element: the first defines an inert fragment of HTML used as a blueprint, the second marks the gaps to fill inside that blueprint once it has been cloned and attached to the shadow DOM. One without the other is rarely useful: a template with no slot cannot receive any outside content, and a slot outside any shadow DOM never distributes any outside content, since it has no host component to attach to.
Dropping a <slot> into an ordinary HTML page, outside the definition of a custom element, triggers no error, but it does not trigger any content distribution either: with no shadow DOM to attach to, there is no outside content to insert into it. The tag is not hidden for that: it simply displays whatever it contains, as written. This trips up many people discovering the tag by testing an isolated example without having set up a shadow DOM: seeing the content appear can wrongly suggest the slot mechanism worked.
Frequently asked questions
slot work with frameworks like React or Vue?Vue has its own slot system, largely inspired by this tag but handled by its rendering engine rather than by the browser. React does not use <slot> natively and instead relies on the children prop, which answers the same need with a different syntax.
slot?Yes, every element sharing the same slot attribute lands together in the matching spot, in the order they appear in the original HTML. Nothing forces a named slot to receive only a single element.
slot's emptiness be checked in JavaScript?The assignedNodes() method called on the slot element returns the list of nodes assigned to it. An empty list, once insignificant text nodes are discarded, means the slot received no content and is therefore showing its fallback content.