demo · v133
:has(:open) — ancestor reacts to descendant state
The real power of :open appears when you combine it with :has(). The page, the toolbar, even body can react to whether any descendant widget is open — without a single line of JavaScript.
:has() + :open is not supported here. Chrome 133+ required.A panel is open — the page background dimmed to focus your attention.
toolbar — recolours when <select> picker is open
accordion list — page reacts when any item is open
Panel one
Some content.
Panel two
More content.
Panel three
Even more content.
the rules
/* Page dims when any panel is open */
body:has(details:open) .stage { background: var(--bg-stone); }
body:has(details:open) .floating-hint { display: block; }
/* Toolbar recolours when one of its <select> pickers is open */
.toolbar:has(select:open) { background: var(--accent-blue); }
.toolbar:has(select:open) select { background: white; color: black; }
Three classic UI patterns now expressible in CSS only:
- Backdrop dim when any panel/disclosure is open.
- Toolbar visual emphasis while a picker is showing.
- Modal-ish “focus mode” on a section without JS state.