Entry 06
:has() for parent and page state
Use it wherever a script adds a class to a parent because of what it contains or what state a child is in.
Code
article:has(img) { grid-column: span 2; }
h2:has(+ p) { margin-block-end: 0; }
form:has(:focus-visible) { background: var(--surface-raised); }
html { scrollbar-gutter: stable; }
html:has(dialog:modal) { overflow: hidden; }Why it works, the rules and the credits
Why it works
:has()matches an element by its descendants or following siblings, and it accepts state pseudo-classes. Content and form state can style any ancestor.- On the root it works as a page-wide listener. The last rule locks page scroll while a modal dialog is open and lifts the lock when it closes, with nothing to clean up.
Rules
:modalmatchesshowModal()only, so a non-modal dialog does not lock the page.- Keep
scrollbar-gutter: stablewith the scroll lock. Without it the page shifts sideways when the scrollbar disappears. The reset sets it. :has()cannot be nested inside:has().
Support
- Chrome
- 105
- Firefox
- 121
- Safari
- 15.4
Credits
Borrowed from: Jen Simmons, Using :has() as a CSS Parent Selector and much more, 2022-08-18 · Josh W. Comeau, The Undeniable Utility Of CSS :has, 2024-09-09 · Chris Coyier, Scroll-Locked Dialogs, 2024-02-19