The <slot> Element
The <slot> element is a placeholder inside a Shadow DOM
tree that gets filled in with markup provided by whoever uses the
component. It is how Web Components support "content projection" — letting
a component's light-DOM children appear inside its encapsulated shadow
tree, in exactly the position the component author designates.
Why Slots Exist
Once an element has a shadow root, its normal children (the "light DOM")
are no longer rendered automatically — the shadow tree takes over what is
displayed. Without a mechanism to reintroduce that content, encapsulation
would make components far less flexible: consumers could not customize what
appears inside a component. <slot> is that mechanism.
Default (Unnamed) Slot
A <slot> with no name attribute is the
default slot. Any light-DOM child of the host element that is not assigned
to a named slot gets projected there.
default-slot.html
<script>
class InfoBox extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' })
shadow.innerHTML = `
<style>
.box { border: 1px solid #ccc; padding: 12px; border-radius: 6px; }
</style>
<div class="box">
<slot>Default text if nothing is provided</slot>
</div>
`
}
}
customElements.define('info-box', InfoBox)
</script>
<info-box>This text is projected into the default slot.</info-box>
<info-box></info-box>First <info-box>: a bordered box containing
"This text is projected into the default slot."
Second <info-box>: a bordered box containing the fallback
"Default text if nothing is provided"<slot> tag in the shadow tree is fallback content — it only renders when the host element supplies nothing for that slot.Named Slots
A component often needs more than one insertion point — a header, a body,
a footer. Named slots handle this: give the <slot> a{' '}
name attribute in the shadow tree, then mark the
corresponding light-DOM element with a matching slot
attribute.
named-slots.html
<script>
class UserCard extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' })
shadow.innerHTML = `
<style>
.card { border: 1px solid #ddd; border-radius: 8px; padding: 16px; }
.card header { font-weight: bold; margin-bottom: 8px; }
.card footer { margin-top: 8px; color: #666; }
</style>
<div class="card">
<header><slot name="title">Untitled</slot></header>
<slot>No content provided.</slot>
<footer><slot name="meta"></slot></footer>
</div>
`
}
}
customElements.define('user-card', UserCard)
</script>
<user-card>
<span slot="title">Ada Lovelace</span>
<p>Mathematician and writer, considered the first programmer.</p>
<span slot="meta">Joined 1815</span>
</user-card>Elements with
slot="title"are projected into<slot name="title">.Elements with
slot="meta"are projected into<slot name="meta">.Any remaining, un-slotted children (the
<p>here) fall through to the default, unnamed<slot>.
How Slots Relate to Web Component Composition
Slots are one of three pieces that work together to build encapsulated, reusable components:
Piece | Role |
|---|---|
| Defines the inert markup blueprint used to build the shadow tree |
Shadow DOM | Encapsulates that markup and its styles from the rest of the page |
| Lets the encapsulated tree accept and position content supplied by the consumer |
<template>, Shadow DOM, and Custom Elements cover the other two pieces of this picture in depth.Styling Slotted Content
Because projected content still logically "belongs" to the light DOM, the shadow tree's own styles do not apply to it directly. Two CSS pseudo-elements/classes exist for this:
Selector | Targets |
|---|---|
| Projected (light-DOM) elements matching |
| The custom element itself, from inside the shadow-tree stylesheet |
slotted-styling.html
<style>
::slotted(span) {
color: darkslateblue;
font-weight: bold;
}
</style>
<slot></slot>Quick Reference
A
<slot>only has meaning inside a shadow root — it does nothing in regular (light) DOM.Unnamed
<slot>catches any child without aslotattribute; named slots catch children with a matchingslot="...".Fallback content is written directly inside the
<slot>tag and shows only when nothing is projected.Style projected content from the shadow tree with
::slotted().