CSS :host() Pseudo-Class
The CSS :host() pseudo-class selects the shadow host of a web component when that host matches a specified selector. It allows components to change their appearance based on classes, attributes, or states applied to the host element.
:host() Syntax
:host(selector) {
property: value;
}
The :host() pseudo-class accepts a compound selector as its argument. The rule matches the shadow host only when the host matches that selector.
Matching a Class
:host(.featured) {
border-color: #0088cc;
}
This rule matches the shadow host when it has the featured class.
Matching an Attribute
:host([theme="dark"]) {
background-color: #333;
color: #fff;
}
This rule matches the shadow host when its theme attribute has the value dark.
Combining Conditions
:host(.featured[theme="dark"]) {
border: 2px solid #66ccff;
}
Both conditions must match the host for this rule to apply.
Invalid Descendant Selector
/* Invalid */
:host(.card .featured) {
color: #0088cc;
}
The argument cannot contain a descendant combinator. Use a compound selector that describes the host itself.
How :host() Works
Shadow DOM provides an internal document tree for a component. The element that owns the shadow root is called the shadow host.
The :host() pseudo-class is used inside the shadow tree's stylesheet to select that host when a specified condition is satisfied.
HTML Host Element
<my-card class="featured"></my-card>
Shadow DOM Styles
:host {
display: block;
padding: 15px;
border: 1px solid #ccc;
}
:host(.featured) {
border-color: #0088cc;
background-color: #eaf6fc;
}
The first rule applies default styles to the host. The second rule applies additional styles because the host has the featured class.
Creating a Shadow Root
const card = document.querySelector("my-card");
const shadow = card.attachShadow({ mode: "open" });
shadow.innerHTML = `
<style>
:host {
display: block;
padding: 15px;
}
:host(.featured) {
background-color: #eaf6fc;
}
</style>
<p>Content inside the shadow tree.</p>
`;
The stylesheet is inside the shadow root, but its :host() selector checks the class on the outer <my-card> element.
Matching Host Classes
Classes allow a component to provide different visual variations without changing its internal HTML structure.
Featured Component
<my-card class="featured"></my-card>
:host(.featured) {
border: 2px solid #0088cc;
}
The border is applied when the host has the featured class.
Multiple Classes
<my-card class="featured compact"></my-card>
:host(.featured.compact) {
padding: 8px;
}
The rule matches only when both classes are present on the host.
Changing Classes with JavaScript
const card = document.querySelector("my-card");
card.classList.toggle("featured");
When the class changes, the browser updates the matching :host() styles automatically.
Matching Host Attributes
Attribute selectors allow web components to expose configuration options through HTML.
Theme Attribute
<my-card theme="dark"></my-card>
:host([theme="dark"]) {
background-color: #333;
color: #fff;
}
The rule applies when the host's theme attribute is set to dark.
Boolean-Style Attributes
<my-card compact></my-card>
:host([compact]) {
padding: 8px;
}
The selector checks whether the compact attribute is present, regardless of its value.
Changing Attributes with JavaScript
const card = document.querySelector("my-card");
card.setAttribute("theme", "dark");
The browser reevaluates the matching selector after the attribute changes.
Attribute Names
Attributes such as theme and compact are component-specific configuration attributes in these examples. They do not automatically provide behavior unless the component implements it.
Matching Host States
The argument of :host() can include pseudo-classes that describe the host's current state.
Hover State
:host(:hover) {
border-color: #0088cc;
}
This rule matches when the host is hovered.
Keyboard Focus
:host(:focus-visible) {
outline: 2px solid #005fcc;
outline-offset: 2px;
}
This rule applies when the host itself matches :focus-visible. The host must be capable of receiving focus.
Focus Within the Component
:host(:focus-within) {
border-color: #0088cc;
}
The host matches when it or an element within its shadow tree has focus.
Combined Class and State
:host(.featured:hover) {
background-color: #d9effa;
}
The host must have the featured class and be hovered for this rule to apply.
Styling Shadow Content
The :host() pseudo-class can also be used at the beginning of a selector to style internal elements based on the host's classes or attributes.
Styling an Internal Heading
:host(.featured) h3 {
color: #0088cc;
}
This rule styles an <h3> inside the shadow tree when the host has the featured class.
Styling an Internal Container
:host([theme="dark"]) .content {
background-color: #333;
color: #fff;
}
This rule styles the internal .content element when the host uses the dark theme.
Host and Internal Styles Together
:host(.featured) {
border-color: #0088cc;
}
:host(.featured) h3 {
color: #006699;
}
The first rule styles the host. The second styles an internal heading when the same host condition is satisfied.
Shadow DOM Boundaries
These descendant selectors apply to elements inside the component's shadow tree. They do not select arbitrary descendants in the surrounding document.
:host() vs. :host
Both selectors target the shadow host, but the functional form requires an additional condition.
Comparison
| Selector | Matching Behavior |
|---|---|
:host |
Matches the shadow host. |
:host(.featured) |
Matches the host when it has the featured class. |
:host([compact]) |
Matches the host when the compact attribute is present. |
:host(:hover) |
Matches the host while it is hovered. |
Default Styles
:host {
display: block;
padding: 15px;
border: 1px solid #ccc;
}
Conditional Styles
:host(.featured) {
border-color: #0088cc;
}
Use :host for component defaults and :host() for conditional styles.
:host() vs. :host-context()
The :host() pseudo-class checks the host itself. The :host-context() pseudo-class can check the host and its surrounding ancestor context.
Comparison
| Selector | Matching Behavior |
|---|---|
:host(.dark) |
Matches when the host has the dark class. |
:host-context(.dark) |
Matches based on a dark class on the host or an ancestor. |
Host-Based Styling
:host(.dark) {
background-color: #333;
color: #fff;
}
Context-Based Styling
:host-context(.dark) {
background-color: #333;
color: #fff;
}
The :host-context() selector has limited browser support and is deprecated in some browser documentation.
For predictable component styling, prefer a class or attribute directly on the host and use :host().
:host() Specificity
The :host() pseudo-class contributes a specificity of 0-1-0 plus the specificity of its argument.
Specificity Examples
| Selector | Specificity |
|---|---|
:host |
0-1-0 |
:host(.featured) |
0-2-0 |
:host([theme="dark"]) |
0-2-0 |
:host(.featured[compact]) |
0-3-0 |
:host(#special) |
1-1-0 |
:host(.featured) h3 |
0-2-1 |
Conditional Rules
:host {
border: 1px solid #ccc;
}
:host(.featured) {
border-color: #0088cc;
}
When the host has the featured class, the second rule overrides the border color because it has greater specificity.
Important Cascade Consideration
Specificity does not override the special cascade ordering between outer-document styles and shadow-tree styles. Normal declarations from the outer document take precedence over normal shadow-tree host declarations when other relevant cascade factors are equal.
The CSS Cascade
Shadow DOM affects how styles from the surrounding document and the component's shadow tree compete when both apply to the host.
Internal Host Rule
:host(.featured) {
color: #0088cc;
}
This rule belongs inside the component's shadow stylesheet.
External Host Rule
my-card.featured {
color: #cc3333;
}
This rule belongs in the outer document stylesheet.
Normal Declarations
For normal declarations at the same origin, styles applied from the outer document take precedence over host styles declared inside the shadow tree, even when the internal selector has greater specificity.
Important Declarations
The ordering is reversed for !important declarations. Important shadow-tree declarations can take precedence over important outer-document declarations.
Component Customization
Use internal host styles for sensible defaults and CSS custom properties for values that component users should be able to customize.
Limitations
The :host() pseudo-class is designed specifically for styles inside a shadow tree.
Requires Shadow DOM
A normal document stylesheet cannot use :host() to select arbitrary custom elements.
Matches the Host Itself
The argument is tested against the shadow host. It does not search the host's descendants or surrounding ancestors.
Compound Selector Argument
The function accepts a compound selector, not a comma-separated selector list or a selector containing combinators.
External Style Overrides
Normal styles from the outer document can override normal host declarations from inside the shadow tree.
Does Not Create Behavior
The selector changes presentation only. Attributes such as disabled, theme, or compact require appropriate component implementation when they are intended to control behavior.
Accessibility
Conditional host styling can help communicate component states, but it should be used alongside appropriate semantic HTML and accessible behavior.
Visible Focus Indicators
:host(:focus-visible) {
outline: 2px solid #005fcc;
outline-offset: 2px;
}
Use this rule when the host itself can receive keyboard focus.
Disabled Components
:host([disabled]) {
opacity: 0.5;
}
This rule changes the appearance of a host with a disabled attribute. It does not automatically prevent interaction or expose disabled semantics to assistive technologies.
Readable Themes
When implementing light and dark component themes, maintain sufficient contrast between text, backgrounds, borders, and focus indicators.
State Communication
Do not rely on color alone to communicate important states. Use appropriate labels, text, and accessible state information.
Best Practices
- Use
:host()to style a shadow host based on its classes, attributes, or states. - Use
:hostfor default styles that apply to every instance of a component. - Keep the argument focused on conditions that apply to the host itself.
- Use component attributes to expose clear configuration options.
- Use
:host()with descendant selectors to style internal elements conditionally. - Remember the special cascade ordering between outer-document and shadow-tree host styles.
- Preserve accessible focus indicators and meaningful state information.
- Test component styles as classes and attributes change.
:host() Example
This example creates a web component with a default appearance and a featured variation. Select the button to add or remove the featured class from the host. The :host(.featured) rule updates the component's appearance automatically.
HTML
<my-feature-card></my-feature-card>
<button type="button" id="toggle-featured">Toggle Featured</button>
JavaScript
class MyFeatureCard extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
shadow.innerHTML = `
<style>
:host {
display: block;
padding: 15px;
border: 2px solid #ccc;
background-color: #f5f5f5;
color: #333;
}
:host(.featured) {
border-color: #0088cc;
background-color: #eaf6fc;
color: #003366;
}
h3 {
margin: 0 0 8px;
font-size: 1.125rem;
}
p {
margin: 0;
}
</style>
<h3>CSS :host() Example</h3>
<p>Toggle the featured class to change this component.</p>
`;
}
}
customElements.define("my-feature-card", MyFeatureCard);
const card = document.querySelector("my-feature-card");
const button = document.getElementById("toggle-featured");
button.addEventListener("click", () => {
card.classList.toggle("featured");
});
Browser Result
Note: JavaScript only changes the host's class. The visual change is controlled by the :host(.featured) CSS rule inside the shadow tree.
Browser Support
Baseline: Widely available. The :host() pseudo-class is supported in modern versions of Chrome, Edge, Firefox, and Safari as part of Shadow DOM styling.
For current compatibility information, visit Can I Use? and search for :host().
Specifications
The :host() pseudo-class is defined in CSS Scoping Level 1. The specification describes its matching behavior, compound selector argument, and specificity.
