CSS Portal

:state() CSS Pseudo Class

☕
Enjoying this site?

Help keep it running with a small coffee donation. Every bit of support is appreciated!

Buy us a coffee
:state()
CSS Pseudo ClassThis pseudo class is supported by all modern browsers.
Updated 31st December 2025

Description

The :state() pseudo-class is an experimental CSS selector used to style custom elements based on their internal state, as defined through the ElementInternals state API. It allows authors to apply styles when a custom element enters a named state - similar in spirit to how built-in form controls respond to states like :hover or :checked, but fully customizable.

Unlike traditional pseudo-classes, :state() is not automatically managed by the browser. Instead, the state must be explicitly defined and toggled via JavaScript using the element’s internal state map.

What :state() Does

The :state() pseudo-class matches a custom element when it has a specific named state set internally. This makes it possible to create semantic, reusable UI components that expose meaningful visual states without relying on attributes or classes.

Example syntax:

my-toggle:state(active) {
  background-color: green;
}

In this example, the styles apply only when the custom element <my-toggle> is in the active state.

Defining a State (JavaScript)

States are defined using the ElementInternals.states API inside a custom element class:

class MyToggle extends HTMLElement {
  constructor() {
    super();
    this._internals = this.attachInternals();
  }

  activate() {
    this._internals.states.add("active");
  }

  deactivate() {
    this._internals.states.delete("active");
  }
}

customElements.define("my-toggle", MyToggle);

Once the "active" state is added, it can be targeted using :state() in CSS.

Example Usage

<my-toggle id="toggle"></my-toggle>
my-toggle:state(active) {
  border: 2px solid green;
  background: #e6ffe6;
}
document.getElementById("toggle").addEventListener("click", e => {
  e.target.activate();
});

When to Use :state()

Use :state() when:

  • You are building custom elements
  • You want encapsulated, semantic state styling
  • You want to avoid relying on class toggling or data attributes
  • You need better integration with the browser’s styling model

Important Notes

  • :state() only works with custom elements, not standard HTML elements like button.
  • Browser support is currently limited and experimental, so it should be used cautiously in production.
  • It is part of the evolving CSS Selectors Level 4 specification.

Syntax

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

Values

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

Example

<my-toggle-button>Click Me</my-toggle-button>

<script>
class MyToggleButton extends HTMLElement {
constructor() {
super();
// 1. Create the internals object
this._internals = this.attachInternals();
this._checked = false;

this.addEventListener('click', () => {
this._checked = !this._checked;

// 2. Toggle the custom state
if (this._checked) {
this._internals.states.add('--checked');
} else {
this._internals.states.delete('--checked');
}
});
}
}

// Register the element
customElements.define('my-toggle-button', MyToggleButton);
</script>
/* Default style for the custom element */
my-toggle-button {
padding: 10px 20px;
border: 2px solid gray;
cursor: pointer;
display: inline-block;
transition: all 0.3s ease;
}

/* Styling based on the custom internal state */
my-toggle-button:state(--checked) {
background-color: #4CAF50;
color: white;
border-color: #2E7D32;
}

/* You can also use it with other pseudo-classes */
my-toggle-button:state(--checked):hover {
background-color: #45a049;
}
Open in editor

Browser Support

The following information will show you the current browser support for the CSS :state() pseudo class. Hover over a browser icon to see the version that first introduced support for this CSS pseudo class.

This pseudo class is supported by all modern browsers.

Desktop

Chrome
Edge
Firefox
Opera
Safari

Tablets & Mobile

Chrome Android
Firefox Android
Opera Android
Safari iOS
Samsung Internet
Android WebView
-
Supported Unknown Not supported
☕
Enjoying this site?

Help keep it running with a small coffee donation. Every bit of support is appreciated!

Buy us a coffee