v148 · css · interop

User-action pseudo-class top-layer boundary

User-action pseudo-classes (:hover, :active, :focus-within) no longer propagate across the top-layer boundary. When a dialog or popover opens, hover and focus state on the element behind it stays where it is until you close the layer — matching what Firefox and Safari already do.

concepts

  1. Layer Boundary

    Open a real <dialog> with a button inside, hover it, then watch the parent button's :hover state. Before v148, it bled through; after, the boundary holds.

  2. Focus-Within Boundary

    The sibling angle: :focus-within at the top-layer boundary. Open a verification dialog from a focus-styled form card and watch the card's amber state stop propagating in Chrome 148+.

  3. Nested Dialogs Demo

    Open an outer dialog, hover its interactive element, then open an inner dialog on top. In Chrome 148+, hovering inside the inner dialog does not propagate :hover back to the outer dialog — the top-layer boundary blocks it.

  4. Top-Layer Focus Demo

    A live focus monitor shows document.activeElement and which :focus-within selectors are active in real time. Tab between main-page inputs, a modal dialog, and a popover. See how Chrome 148 stops :focus-within propagating across the top-layer boundary — with selector status indicators for body, main, and individual form cards.

  5. Hover & Active Demo

    Side-by-side panels showing :hover and :active behavior when a dialog is open. The Chrome 148 panel blocks pseudo-class propagation at the top-layer boundary — the trigger button stops being "hovered" the moment the dialog opens. The Pre-148 panel simulates the bug where the trigger stayed visually hovered regardless.

why it shipped

The top layer is a separate stacking world — that's how dialogs and popovers escape overflow: hidden and z-index hell. But until this change, Chrome propagated :hover and :focus-within from elements inside the top layer back into their flat-tree ancestors. That meant a button styled to glow on hover would still glow while the user was interacting with a dialog opened from it — visually confusing and inconsistent with other browsers. The boundary now stops that propagation, aligning Chrome with Firefox and Safari.

references

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗