← Chrome 148 reference

v148 · css · developer trial

User action pseudo-class top-layer boundary

Chrome 148 enforces the CSS Selectors 4 rule that :hover, :active, and :focus-within bubble up through ancestors only as far as the nearest top-layer boundary. A popover or dialog element no longer causes the entire document to appear hovered.

Developer trial / behind a flag This feature is in developer trial in Chrome 148 — enable via chrome://flags/#enable-experimental-web-platform-features. It ships as enabled by default in Chrome 149.

at a glance

Status in 148In developer trial (behind a flag)
Ships by defaultChrome 149
Flagchrome://flags/#enable-experimental-web-platform-features
Standards positionFirefox: No signal  ·  Safari: No signal
SpecCSS Selectors Level 4 §user-action pseudos
ChromeStatus6296574159355904 — User action pseudo-class top-layer boundary

why it exists

In CSS, user-action pseudo-classes (:hover, :active, :focus-within) match ancestor elements when a descendant is in the matching state. This is intentional: hovering a button also matches the containing <nav>. However, the CSS Selectors 4 spec says this propagation must stop at a top-layer boundary — the boundary introduced by elements rendered in the top layer, such as <dialog> and elements with popover.

Without this boundary, hovering anything inside an open popover would match :hover all the way up through the entire document, causing unintended hover styles on the page behind the popover.

Source: chromestatus summary + CSS Selectors Level 4 §useraction-pseudos.

what changes

Pseudo-classBefore Chrome 148After Chrome 148
:hoverMatched all ancestors up to <html>, even through dialog/popoverStops propagating at the top-layer boundary
:activeSame — could activate styles in backdrop pageStops at top-layer boundary
:focus-withinCould match the document root when focus was inside a dialogStops at top-layer boundary
Source: chromestatus feature description.

example

<style>
  /* This used to fire when hovering inside the dialog in Chrome < 148 */
  body:hover .page-overlay {
    opacity: 1;
  }
  /* After Chrome 148: :hover on body does NOT match when only elements
     inside the open dialog are hovered */
</style>

<dialog id="dlg">
  <p>Hover me — does the page overlay appear?</p>
  <button>Close</button>
</dialog>
<div class="page-overlay">Should not appear on dialog hover</div>

Checking intent

If you want a style to fire based on whether anything on the page (including inside dialogs) is hovered, use JavaScript and a custom class instead of :hover propagation.

browser support

Chrome148 — now spec-compliant
FirefoxNo signal
SafariNo signal
Source: chromestatus browser views.

see also