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

  1. Hover Boundary Demo

    A card grid with a popover. Chrome 149 prevents the card's :hover highlight from activating while the cursor is inside the popover, which is rendered above the card in the top layer.

  2. Focus-Within Dialog Boundary

    A form with a <dialog> element. In Chrome 149, :focus-within on the parent container stops at the dialog boundary — moving focus inside the dialog no longer lights up the outer container.

  3. Interaction Scope Demo

    Combined demo: hover a popover and watch the underlying card's :hover style; 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.

  4. Active Popover Test

    A host card behind an open popover. State monitor shows the card's :hover and :focus-within in 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.

  5. 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 :hover or :focus-within and where Chrome 149's boundary stops the propagation.

  6. Multi-Popover Hover Test

    Open three nested popover=auto elements above a host card and move your cursor between them. A live state table and event log track :hover on every element simultaneously — confirming that hovering inside any popover leaves all outer elements and the host card in the no-hover state.

    Interactive :hover boundary Event log

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 ↗