CSS ::slotted() Pseudo-Element
The ::slotted() pseudo-element styles elements assigned to slots inside a Shadow DOM component. It allows a component's internal stylesheet to apply styles to selected elements supplied by the page using that component.
Syntax
::slotted(selector) {
property: value;
}
The selector argument identifies the elements assigned to a slot that should receive the styling.
The argument must be a valid compound selector. It cannot contain combinators that select descendants or siblings.
For example:
::slotted(p) {
color: #0066cc;
}
This rule styles paragraph elements assigned directly to slots in the current shadow tree.
A class selector can also be used:
::slotted(.highlight) {
background-color: #ffeb99;
}
This targets assigned elements with the highlight class.
To match any assigned element, use the universal selector:
::slotted(*) {
font-family: Arial, sans-serif;
}
The ::slotted() pseudo-element is intended for stylesheets within Shadow DOM.
It cannot be used in an ordinary document stylesheet to reach into an unrelated component's shadow tree.
How It Works
Web Components can use Shadow DOM to encapsulate their internal HTML structure and CSS.
A <slot> element creates a location where content supplied by the component's user can appear.
The ::slotted() pseudo-element allows CSS inside the shadow tree to style elements assigned to those slots.
The process involves four steps:
- Create a custom element with an attached shadow root.
- Add one or more
<slot>elements to its shadow tree. - Place content inside the custom element in the document.
- Use
::slotted()in the shadow stylesheet to style assigned elements.
For example, a shadow tree might contain:
<style>
::slotted(p) {
color: #0066cc;
}
</style>
<slot></slot>
The page using the component supplies a paragraph:
<custom-panel>
<p>This paragraph is assigned to the slot.</p>
</custom-panel>
When the paragraph is assigned to the slot, the shadow stylesheet can apply the blue text color.
The paragraph remains part of the document's light DOM. It is displayed through the slot rather than moved into the shadow tree.
Understanding Shadow DOM and Slots
Shadow DOM provides a separate DOM tree attached to an element, commonly called the shadow host.
The shadow tree can contain its own HTML, styles, and slots.
Consider this component structure:
<div class="panel">
<h3>Panel Heading</h3>
<slot></slot>
</div>
The <slot> element represents a placeholder for content supplied outside the shadow tree.
For example:
<custom-panel>
<p>Content supplied by the page.</p>
</custom-panel>
The paragraph is assigned to the unnamed slot.
A stylesheet inside the shadow tree can use:
::slotted(p) {
font-weight: bold;
color: #0066cc;
}
This styles the assigned paragraph without requiring the component to modify the paragraph's HTML.
The slot itself and the assigned paragraph are different elements.
Use the slot selector to style the actual <slot> element, and ::slotted() to style assigned elements.
Matching Slotted Elements
The ::slotted() pseudo-element can match assigned elements by element name, class, ID, attribute, or other supported simple selector combinations.
For example:
::slotted(h2) {
color: #0066cc;
}
::slotted(.notice) {
background-color: #eef5ff;
}
::slotted([data-status="active"]) {
font-weight: bold;
}
The first rule targets assigned <h2> elements.
The second rule targets assigned elements with the notice class.
The third rule targets assigned elements with a data-status attribute equal to active.
Selectors can also combine conditions on the same element:
::slotted(p.notice) {
color: #0066cc;
}
This matches an assigned paragraph that also has the notice class.
The selector does not match an element merely because it is a descendant of an assigned element.
Styling Named Slots
Named slots allow a component to provide different locations for different types of content.
For example, a component might define a heading slot and a content slot:
<slot name="heading"></slot>
<slot name="content"></slot>
The page assigns elements to those slots using the slot attribute:
<custom-card>
<h3 slot="heading">Card Heading</h3>
<p slot="content">Card description.</p>
</custom-card>
Inside the shadow stylesheet, each slot's assigned elements can be styled separately:
slot[name="heading"]::slotted(*) {
color: #0066cc;
font-weight: bold;
}
slot[name="content"]::slotted(*) {
color: #444;
line-height: 1.6;
}
The first rule styles elements assigned to the heading slot.
The second rule styles elements assigned to the content slot.
Using named slots helps components maintain consistent styling across different types of supplied content.
Selector Arguments
The argument inside ::slotted() must be a compound selector, meaning it can combine selectors that describe the same element without using combinators.
| Selector | Description |
|---|---|
::slotted(*) |
Matches any assigned element. |
::slotted(p) |
Matches assigned paragraphs. |
::slotted(.notice) |
Matches assigned elements with the notice class. |
::slotted(#intro) |
Matches an assigned element with the intro ID. |
::slotted([lang="en"]) |
Matches assigned elements with the specified language attribute. |
::slotted(p.notice) |
Matches assigned paragraphs with the notice class. |
Descendant selectors cannot be used inside the argument:
/* Invalid */
::slotted(div p) {
color: #0066cc;
}
The space between div and p is a descendant combinator, which is not permitted.
To style a paragraph nested inside an assigned element, use a stylesheet that can directly target that paragraph, such as the document stylesheet.
Example
The following example creates a custom card component using Shadow DOM and named slots.
The component's shadow stylesheet uses ::slotted() to style the supplied heading and description.
HTML:
<demo-slotted-card>
<h3 slot="heading">HTML and CSS</h3>
<p slot="content">Learn how Shadow DOM slots display content inside reusable components.</p>
</demo-slotted-card>
JavaScript:
class DemoSlottedCard extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
shadow.innerHTML = `
<style>
.card {
padding: 20px;
border: 1px solid #ccc;
border-radius: 6px;
background-color: #f5f9ff;
font-family: Arial, sans-serif;
}
slot[name="heading"]::slotted(*) {
display: block;
margin: 0 0 10px;
color: #0066cc;
font-size: 20px;
}
slot[name="content"]::slotted(*) {
display: block;
margin: 0;
color: #333;
line-height: 1.6;
}
</style>
<div class="card">
<slot name="heading"></slot>
<slot name="content"></slot>
</div>
`;
}
}
customElements.define("demo-slotted-card", DemoSlottedCard);
HTML and CSS
Learn how Shadow DOM slots display content inside reusable components.
The browser creates a custom card with a light background and border.
The heading appears blue because it is assigned to the heading slot.
The description appears dark gray because it is assigned to the content slot.
The ::slotted() rules are defined inside the component's shadow stylesheet.
The heading and paragraph remain in the light DOM, while the component controls their presentation through its slot styling.
Note: This Browser Result requires JavaScript because the custom element and its shadow tree must be created before the ::slotted() styling can be demonstrated.
Styling Nested Elements
The ::slotted() pseudo-element matches elements directly assigned to a slot, not arbitrary descendants of those elements.
For example:
<custom-panel>
<div>
<p>Nested paragraph</p>
</div>
</custom-panel>
If the shadow tree contains an unnamed slot, the <div> is assigned to that slot.
The paragraph is a descendant of the assigned element, but it is not itself assigned to the slot.
This rule can style the assigned <div>:
::slotted(div) {
color: #0066cc;
}
The paragraph may inherit the text color from its parent.
However, this rule does not directly select the nested paragraph:
/* Invalid */
::slotted(div) p {
font-weight: bold;
}
The ::slotted() pseudo-element cannot be followed by a descendant combinator to select elements inside the assigned element.
If nested content needs its own styles, use the document stylesheet or another appropriate styling mechanism.
For example:
custom-panel div p {
font-weight: bold;
}
This document-level selector can target the paragraph because the supplied content remains in the light DOM.
::slotted() vs. ::part()
The ::slotted() and ::part() pseudo-elements both relate to Shadow DOM, but they style different types of elements.
| Feature | ::slotted() | ::part() |
|---|---|---|
| Purpose | Styles elements assigned to slots. | Styles exposed elements inside a shadow tree. |
| Stylesheet location | Inside the shadow tree containing the slot. | Outside the shadow tree exposing the part. |
| Target elements | Slotted light DOM elements. | Shadow DOM elements with exported part names. |
| Argument | A compound selector. | One or more part names. |
| Typical use | Component styling of supplied content. | Page styling of exposed component internals. |
For example, inside a shadow stylesheet:
::slotted(.heading) {
color: #0066cc;
}
This styles an assigned element with the heading class.
By comparison, a component might expose an internal element using:
<div part="header">Card Header</div>
The page can then style that exposed part:
custom-card::part(header) {
background-color: #eef5ff;
}
Use ::slotted() when a component needs to style supplied content.
Use ::part() when a component intentionally exposes internal elements for external styling.
Supported CSS Properties
The ::slotted() pseudo-element can apply ordinary CSS styling properties to matching assigned elements.
| Property | Purpose |
|---|---|
color |
Changes the assigned element's text color. |
background-color |
Changes the assigned element's background. |
font-size |
Controls text size. |
font-weight |
Controls text weight. |
line-height |
Controls line spacing. |
padding |
Adds space inside the assigned element. |
margin |
Controls space around the assigned element. |
border |
Adds or changes borders. |
border-radius |
Rounds corners. |
display |
Controls the assigned element's layout behavior. |
For example:
::slotted(.message) {
display: block;
padding: 12px;
border: 1px solid #0066cc;
border-radius: 4px;
background-color: #eef5ff;
color: #333;
}
This styles assigned elements with the message class as bordered message blocks.
Unlike highlight pseudo-elements such as ::selection, ::slotted() is not limited to text highlight properties.
Normal CSS cascade rules still apply. Styles defined directly on the assigned element in the document can override competing declarations from the shadow stylesheet.
Limitations
The ::slotted() pseudo-element has several important limitations.
- It is used in Shadow DOM stylesheets associated with slots.
- It matches elements assigned to slots, not arbitrary descendants of those elements.
- Its argument must be a compound selector without combinators.
- It cannot directly style text nodes assigned to a slot.
- It cannot select internal shadow elements that are unrelated to slot assignment.
- It does not create slots or assign content to them.
- It does not replace the
::part()pseudo-element for styling exposed shadow components from outside.
For example, the following selector is invalid:
/* Invalid */
::slotted(.card .title) {
color: #0066cc;
}
The descendant combinator is not allowed inside ::slotted().
Instead, style the assigned element directly or use a document-level selector for nested content.
For component development, keep slot structures and styling responsibilities clear so that supplied content remains predictable.
Accessibility Considerations
The ::slotted() pseudo-element changes the presentation of assigned elements without changing their HTML semantics.
Follow these accessibility practices:
- Use appropriate semantic HTML elements for supplied content.
- Maintain sufficient contrast between text and background colors.
- Preserve visible focus indicators for slotted links, buttons, and form controls.
- Avoid using CSS to hide essential content or instructions.
- Ensure components remain usable with keyboard navigation.
- Test content assigned to both named and unnamed slots.
- Do not rely on visual styling alone to communicate meaning.
- Test custom components with assistive technologies.
For example, a slotted link can receive a visible focus indicator:
::slotted(a:focus-visible) {
outline: 2px solid #0066cc;
outline-offset: 3px;
}
This helps keyboard users identify the focused link.
Slotted content retains its original semantic meaning, so a slotted heading remains a heading and a slotted button remains a button.
Browser Support
The ::slotted() pseudo-element is widely available in modern browsers, including Chrome, Edge, Firefox, Safari, and Opera.
It is part of the standard Shadow DOM styling model used by Web Components.
Basic support for matching assigned elements with compound selectors is well established.
For example:
::slotted(.notice) {
color: #0066cc;
}
This selector works in supporting browsers when placed inside a shadow stylesheet with an appropriate slot assignment.
Because ::slotted() depends on Shadow DOM, the component must also have a shadow root and slot structure.
For current compatibility information, visit Can I Use? and search for ::slotted() or Shadow DOM.
Specifications
The ::slotted() pseudo-element is defined in the CSS Scoping Module Level 1 .
The specification defines how ::slotted() matches assigned elements and how it participates in styling across shadow tree boundaries.
Related features include the <slot> element, the slot attribute, Shadow DOM, :host, and ::part().
