This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
The ::slotted() CSS pseudo-element represents any element that has been placed into a slot inside an HTML template (see Using templates and slots for more information).
This only works when used inside CSS placed within a shadow DOM. Note that this selector won't select a text node placed into a slot; it only targets actual elements.
/* This CSS is being applied inside the shadow DOM. */
::slotted(.content) {
background-color: aqua;
}
h2 ::slotted(span) {
background: silver;
}
<template id="card-template">
<div>
<h2><slot name="caption">title goes here</slot></h2>
<slot name="content">content goes here</slot>
</div>
</template>
<my-card>
<span slot="caption">Error</span>
<p class="content" slot="content">Build failed!</p>
</my-card>
customElements.define(
"my-card",
class extends HTMLElement {
constructor() {
super();
const template = document.getElementById("card-template");
const shadow = this.attachShadow({ mode: "open" });
shadow.appendChild(template.content.cloneNode(true));
const elementStyle = document.createElement("style");
elementStyle.textContent = `
div {
width: 200px;
border: 2px dotted red;
border-radius: 4px;
}`;
shadow.appendChild(elementStyle);
const cssTab = document.querySelector("#css-output");
const editorStyle = document.createElement("style");
editorStyle.textContent = cssTab.textContent;
shadow.appendChild(editorStyle);
cssTab.addEventListener("change", () => {
editorStyle.textContent = cssTab.textContent;
});
}
},
);
/* Selects any element placed inside a slot */
::slotted(*) {
font-weight: bold;
}
/* Selects any <span> placed inside a slot */
::slotted(span) {
font-weight: bold;
}
::slotted(<compound-selector>) {
/* ... */
}
In this example, we use a template with three slots:
<template id="person-template">
<div>
<h2>Personal ID Card</h2>
<slot name="person-name">NAME MISSING</slot>
<ul>
<li><slot name="person-age">AGE MISSING</slot></li>
<li><slot name="person-occupation">OCCUPATION MISSING</slot></li>
</ul>
</div>
</template>
We define the <person-details> custom element. In this case, we add styles with JavaScript, though we could have added them in a <style> block within the <template> with the same effect:
customElements.define(
"person-details",
class extends HTMLElement {
constructor() {
super();
let template = document.getElementById("person-template");
let templateContent = template.content;
const shadowRoot = this.attachShadow({ mode: "open" });
let style = document.createElement("style");
style.textContent =
"div { padding: 10px; border: 1px solid gray; width: 200px; margin: 10px; }" +
"h2 { margin: 0 0 10px; }" +
"ul { margin: 0; }" +
"p { margin: 10px 0; }" +
"::slotted(*) { color: gray; font-family: sans-serif; } " +
"::slotted(span) {text-decoration: underline;} ";
shadowRoot.appendChild(style);
shadowRoot.appendChild(templateContent.cloneNode(true));
}
},
);
When filling the style element with content, you'll see that we select all slotted elements (::slotted(*)) and give them a different font and color. This differentiates them from the slots that haven't been filled. We styled all the slotted <span>s (::slotted(span)) to differentiate the <span>s from the <p>s.
Our markup includes three custom elements, including a custom element with an invalid slot name in a source order that differs from the <template>:
<person-details> <p slot="person-name">Wonder Woman</p> <span slot="person-age">Immortal</span> <span slot="person-occupation">Superhero</span> </person-details> <person-details> <p slot="person-name">Malala Yousafzai</p> <span slot="person-age">17</span> <span slot="person-occupation">Activist</span> </person-details> <person-details> <span slot="person-age">44</span> <span slot="not-a-slot-name">Time traveler</span> <p slot="person-name">Dr. Who</p> </person-details>
| Specification |
|---|
| CSS Scoping Module Level 1> # slotted-pseudo> |
| Desktop | Mobile | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
::slotted |
50 | 79 | 63 | 37 | 10 | 50 | 63 | 37 | 10 | 5.0 | 50 | 10 |
:host:host():host-context():has-slottedslot attribute<slot> element<template> element
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted