v149 · CSS
User action pseudo class top layer boundary
:hover, :active, and :focus-within now stop propagating upward when they encounter a top-layer element — so hovering over a popover no longer triggers :hover on the popover's unrelated parent.
concepts
-
Hover Boundary Demo
A card grid with a popover. Chrome 149 prevents the card's
:hoverhighlight from activating while the cursor is inside the popover, which is rendered above the card in the top layer. -
Focus-Within Dialog Boundary
A form with a
<dialog>element. In Chrome 149,:focus-withinon the parent container stops at the dialog boundary — moving focus inside the dialog no longer lights up the outer container. -
Interaction Scope Demo
Combined demo: hover a popover and watch the underlying card's
:hoverstyle; tab into a dialog and watch the outer container's:focus-within. An event log surfaces exactly when the boundary fires vs. when state leaks in older browsers. -
Active Popover Test
A host card behind an open popover. State monitor shows the card's
:hoverand:focus-withinin real time — interact inside the popover and verify that neither pseudo-class leaks to the host card in Chrome 149+. Includes a reference table of which actions leak in pre-149 browsers. -
Cascade Trace
Step through four scenarios — hover card only, hover inside popover, focus in dialog, nested popovers — and see a colour-coded DOM tree showing exactly which ancestors gain
:hoveror:focus-withinand where Chrome 149's boundary stops the propagation. -
Multi-Popover Hover Test
Open three nested
popover=autoelements above a host card and move your cursor between them. A live state table and event log track:hoveron every element simultaneously — confirming that hovering inside any popover leaves all outer elements and the host card in the no-hover state.
why it shipped
Top-layer elements — <dialog>, popover elements, fullscreen elements — are visually positioned outside their DOM ancestors even though they remain in the tree. This visual disconnect meant that :hover and :focus-within would "leak" upward to unrelated ancestors when the user interacted with a popover. A dropdown menu hovering over a card would unexpectedly trigger the card's :hover styles. Chrome 149 aligns with the CSS Selectors Level 4 spec by introducing a boundary: user-action pseudo-classes match ancestors only up to the first top-layer element in the chain, fixing a widespread source of unintended hover effects.
references
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗