v150 · CSS
Media element pseudo-classes
CSS pseudo-classes that match <audio> and <video> elements based on their playback state — :playing, :paused, :seeking, :buffering, :stalled, :muted, and :volume-locked — so you can style media controls purely in CSS without JavaScript event listeners.
concepts
-
Media Mood Board
A styled music player whose background, border glow, and icon all update automatically through
:playing,:paused, and:muted— zero JavaScript for the visual transitions. -
State Inspector
Live demo of every media pseudo-class. Play, pause, seek, and mute a video and watch each
:pseudo-classtoggle on and off in a real-time indicator panel. -
Playlist UI
A full five-track playlist where the active row highlights, the album art pulses, and the track number transforms into a ♫ note — all via
audio:playing + .track-rowCSS sibling selectors. No JavaScript for any visual state. -
Buffering States
An interactive simulator for the two network-dependent pseudo-classes:
:buffering(waiting for data while playing) and:seeking(scrubbing to a new position). Toggle each state and watch the spinner overlay, pill indicators, and active CSS rule update — shows the less-covered half of the media pseudo-class set. -
Video Gallery
Six simulated video cards styled entirely by CSS
:playing,:paused, and:mutedpseudo-classes — blue thumbnail when playing, amber when paused, 🔇 overlay when muted, progress bar color tied to:playing. No JavaScript reads or writes class names for playback state; it's all in the CSS. -
Compatibility Lab
Probes all 7 media pseudo-classes with
CSS.supports('selector(audio:playing)'), shows a CSS-only live indicator for the:playing,:paused, and:mutedstates, and provides the exact JavaScript event-listener fallback pattern to use in browsers that don't support them yet. -
Production UX Pattern
Three real-world patterns — a music player with CSS-only dark mode on play, a video player with a CSS-driven pause overlay and mute badge, and a playlist with CSS sibling highlighting. Each shows the exact production CSS and HTML to copy using
:has(audio:playing), sibling combinators, and:muted.
why it shipped
Before this feature, styling a media element differently when it was playing vs paused required attaching play and pause event listeners, toggling classes manually, and keeping JavaScript state in sync with the DOM. The pattern is so common that every media player library reinvents it. CSS pseudo-classes like :hover and :focus have long let developers respond to interaction state without JavaScript — media pseudo-classes extend that philosophy to playback state. Firefox shipped them first (Firefox 127), giving Chrome developers a compelling interop story. With both engines supporting them, the pattern can finally replace the event-listener boilerplate.
references
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗