:state() CSS pseudo-class

Baseline 2024
Newly available

Since May 2024, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

The :state() CSS pseudo-class matches custom elements that have the specified custom state.

Syntax

css
:state(<custom identifier>) {
  /* ... */
}

Parameters

The :state() pseudo-class takes as its argument a custom identifier that represents the state of the custom element to match.

Description

Elements can transition between states due to user interaction and other factors. For instance, an element can be in the "hover" state when a user hovers over the element, or a link can be in the "visited" state after a user clicks on it. Elements provided by browsers can be styled based on these states using CSS pseudo-classes such as :hover and :visited. Similarly, autonomous custom elements (custom elements that are not derived from built-in elements) can expose their states, allowing pages that use the elements to style them using the CSS :state() pseudo-class.

The states of a custom element are represented by string values. These values are added to or removed from a CustomStateSet object associated with the element. The CSS :state() pseudo-class matches an element when the identifier, passed as an argument, is present in the CustomStateSet of the element.

The :state() pseudo-class can also be used to match custom states within the implementation of a custom element. This is achieved by using :state() within the :host() pseudo-class function, which matches a state only within the shadow DOM of the current custom element.

Additionally, the ::part() pseudo-element followed by the :state() pseudo-class allows matching on the shadow parts of a custom element that are in a particular state. (Shadow parts are parts of a custom element's shadow tree that are explicitly exposed to a containing page for styling purposes.)

Examples

Matching a custom state

This CSS shows how to change the border of the autonomous custom element <labeled-checkbox> to red when it is in the "checked" state.

css
labeled-checkbox {
  border: dashed red;
}
labeled-checkbox:state(checked) {
  border: solid;
}

For a live example of this code in action, see the Matching the custom state of a custom checkbox element example on the CustomStateSet page.

Matching a custom state in a custom element's shadow DOM

This example shows how the :state() pseudo-class can be used within the :host() pseudo-class function to match custom states within the implementation of a custom element.

The following CSS injects a grey [x] before the element when it is in the "checked" state.

css
:host(:state(checked))::before {
  content: "[x]";
}

For a live example of this code in action, see the Matching the custom state of a custom checkbox element example on the CustomStateSet page.

Matching a custom state in a shadow part

This example shows how the :state() pseudo-class can be used to target the shadow parts of a custom element.

Shadow parts are defined and named using the part attribute. For example, consider a custom element named <question-box> that uses a <labeled-checkbox> custom element as a shadow part named checkbox:

js
shadowRoot.innerHTML = `<labeled-checkbox part='checkbox'>Yes</labeled-checkbox>`;

The CSS below shows how the ::part() pseudo-element can be used to match against the 'checkbox' shadow part. It then shows how the ::part() pseudo-element followed by the :state() pseudo-class can be used to match against the same part when it is in the checked state.

css
question-box::part(checkbox) {
  color: red;
}

question-box::part(checkbox):state(checked) {
  color: green;
  outline: dashed 1px green;
}

For a live example of this code in action, see the Matching a custom state in a shadow part of a custom element example on the CustomStateSet page.

Specifications

Specification
HTML
# selector-custom

Browser compatibility

desktop mobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Custom state pseudo-class selector (:state())
Chrome – Partial support
Chrome 90 – 124 (Release date: 2021-04-13)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
Chrome – Full support
Chrome 125 (Release date: 2024-05-14)
footnote Full support
Edge – Partial support
Edge 90 – 124 (Release date: 2021-04-15)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
Edge – Full support
Edge 125 (Release date: 2024-05-17)
footnote Full support
Firefox – Full support
Firefox 126 (Release date: 2024-05-14)
footnote Full support
Opera – Partial support
Opera 76 – 110 (Release date: 2021-04-28)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
Opera – Full support
Opera 111 (Release date: 2024-06-12)
footnote Full support
Safari – Full support
Safari 17.4 (Release date: 2024-03-05)
footnote Full support
Chrome Android – Partial support
Chrome Android 90 – 124 (Release date: 2021-04-13)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
Chrome Android – Full support
Chrome Android 125 (Release date: 2024-05-14)
footnote Full support
Firefox for Android – Full support
Firefox for Android 126 (Release date: 2024-05-14)
footnote Full support
Opera Android – Partial support
Opera Android 64 – 82 (Release date: 2021-05-25)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
Opera Android – Full support
Opera Android 83 (Release date: 2024-06-25)
footnote Full support
Safari on iOS – Full support
Safari on iOS 17.4 (Release date: 2024-03-05)
footnote Full support
Samsung Internet – Partial support
Samsung Internet 15 – 26 (Release date: 2021-08-13)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
Samsung Internet – Full support
Samsung Internet 27 (Release date: 2024-11-06)
footnote Full support
WebView Android – Partial support
WebView Android 90 – 124 (Release date: 2021-04-13)
footnote Partial support
footnote Uses a dashed-ident (such as :--foo) instead of :state().
WebView Android – Full support
WebView Android 125 (Release date: 2024-05-14)
footnote Full support
WebView on iOS – No support
WebView on iOS
footnote No support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
Partial support
Partial support
No support
No support
Has more compatibility info.

See also