Skip to content

The slot Attribute

Global Attribute

The slot attribute is used in Web Components to assign content to specific slots within a Shadow DOM template. It enables flexible content projection, allowing component users to customize parts of a component while maintaining encapsulation.

<my-component>
<p slot="header">This goes in the header slot</p>
<p>This goes in the default slot</p>
</my-component>
ValueDescription
Slot name (string)Name of the slot to project content into
(empty/omitted)Content goes into the default (unnamed) slot
Result
Result
Result
Result

The slot attribute assigns light DOM content to specific slots in the shadow DOM:

<!-- Light DOM (what the user writes) -->
<my-component>
<p slot="header">Header content</p>
<p>Default content</p>
</my-component>
<!-- Shadow DOM (inside the component) -->
<template>
<div class="component">
<header>
<slot name="header"></slot> <!-- Receives slot="header" content -->
</header>
<main>
<slot></slot> <!-- Receives content without slot attribute -->
</main>
</div>
</template>

Named slots: Require slot="name" attribute

<p slot="header">Goes to <slot name="header"></slot></p>

Default slot: No slot attribute needed

<p>Goes to <slot></slot></p>
<!-- Good: Clear, semantic names -->
<card-component>
<img slot="thumbnail">
<h3 slot="title">Title</h3>
<p slot="description">Description</p>
<button slot="action">Action</button>
</card-component>
<!-- Bad: Generic names -->
<card-component>
<img slot="slot1">
<h3 slot="slot2">Title</h3>
</card-component>
// In shadow DOM, provide defaults
shadow.innerHTML = `
<slot name="title">Default Title</slot>
<slot>Default content</slot>
`;
/**
* <my-component>
* Available slots:
* - header: Component header content
* - default: Main content
* - footer: Footer actions
* </my-component>
*/
class MyComponent extends HTMLElement {
// ...
}
/* In shadow DOM */
::slotted([slot="title"]) {
font-size: 24px;
color: #1e293b;
}
::slotted(img) {
max-width: 100%;
}
class MyComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
// Get all slotted elements
const slot = this.shadowRoot.querySelector('slot[name="header"]');
const elements = slot.assignedElements();
console.log('Slotted elements:', elements);
// Listen for slot changes
slot.addEventListener('slotchange', (e) => {
console.log('Slot content changed');
});
}
}
const element = document.createElement('p');
element.textContent = 'Dynamic content';
element.slot = 'header'; // Assign to named slot
myComponent.appendChild(element);
<product-card>
<img slot="image" src="product.jpg">
<h3 slot="title">Product Name</h3>
<!-- Description slot is optional -->
<span slot="price">$99.99</span>
</product-card>
<custom-list>
<div slot="item">
<img src="icon1.png">
<span>Item 1</span>
</div>
<div slot="item">
<img src="icon2.png">
<span>Item 2</span>
</div>
</custom-list>
<dialog-box>
<h2 slot="header">Confirm Action</h2>
<p slot="body">Are you sure you want to continue?</p>
<div slot="footer">
<button>Cancel</button>
<button>Confirm</button>
</div>
</dialog-box>
BrowserSupport
Chrome53+
Firefox63+
Safari10+
Edge79+