v152 ยท CSS
Production UX Pattern
Three real-world patterns โ a music player with CSS-only dark mode on play, a video player with CSS-driven pause overlay and mute badge, and a playlist with CSS sibling highlighting. Each shows the exact production CSS and HTML using :has(audio:playing), sibling combinators, and :muted.
Pattern: :has(audio:playing) for dark-mode-on-play
Press play โ the card goes dark and the album art spins. No JS.
๐ต
Sample Track
.music-player {
background: var(--bg-stone);
transition: background 0.3s;
}
/* CSS-only: dark mode when audio is playing */
.music-player:has(audio:playing) {
background: var(--text-black);
color: var(--bg-ivory);
}
/* Spin animation on play */
.music-player:has(audio:playing) .album-art {
animation: spin 3s linear infinite;
}
/* Text status via generated content */
.track-status::before {
content: 'โธ paused';
}
.music-player:has(audio:playing) .track-status::before {
content: 'โถ playing';
color: var(--accent-emerald);
}
/* Mute badge in generated content */
.music-player:has(audio:muted) .track-status::after {
content: ' ๐';
}
Pattern: sibling combinator for pause overlay + mute badge
Play/pause and mute the video. Overlay and badge are CSS-only.
๐ MUTED
.video-wrapper { position: relative; display: inline-block; }
.video-overlay {
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
pointer-events: none;
transition: opacity 0.3s;
}
/* Hide overlay while playing */
video:playing ~ .video-overlay { opacity: 0; }
video:paused ~ .video-overlay { opacity: 1; }
/* Show spinner while buffering */
.spinner { display: none; }
video:buffering ~ .video-overlay .spinner { display: block; }
/* Mute badge */
.mute-badge { position: absolute; top: 0.4rem; right: 0.4rem; }
video:muted ~ .mute-badge { opacity: 1; }
video:not(:muted) ~ .mute-badge { opacity: 0; }
Pattern: :has(audio:playing) for playlist row highlight
Play the audio to highlight the active track row.
Current Track
Next Track
Another Song
/* Highlight active row when audio is playing */
#pl-audio:playing ~ .playlist .pl-now {
background: var(--bg-stone);
border-left-color: var(--accent-emerald);
}
/* Status text via CSS */
.pl-status::before { content: 'โธ'; }
#pl-audio:playing ~ .playlist .pl-now .pl-status::before {
content: 'โถ';
color: var(--accent-emerald);
}
#pl-audio:paused ~ .playlist .pl-now .pl-status::before { content: 'โธ'; }