Three modern selectors. One page.
:has(), container queries, and dynamic viewport units —
each with a tiny working demo and the rule that makes it go.
1. The parent selector — :has()
The whole form below is a single CSS rule. The label glows when its
input has focus. The submit button dims while any input has a
:invalid value, because .form-demo:has(input:invalid:not(:placeholder-shown))
matches the parent.
2. Container queries — @container
Both cards below have the same markup. The left one sits in a narrow column, the right one in a wide column. The card's own width decides whether it lays out vertically or horizontally — not the viewport.
Below 420 px, I stack.
Above 420 px, I sit on a row.
3. Dynamic viewport units — dvh
On Safari, scrolling collapses the toolbar and the visible viewport
height grows. 100dvh tracks the current height
and resizes accordingly, while 100vh stays fixed at the
large size. The box below is 50dvh.
Also available: svh (small) and lvh (large) for the locked extremes.