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.
chrome://flags/#enable-experimental-web-platform-features. It ships as enabled by default in Chrome 149.
at a glance
| Status in 148 | In developer trial (behind a flag) |
|---|---|
| Ships by default | Chrome 149 |
| Flag | chrome://flags/#enable-experimental-web-platform-features |
| Standards position | Firefox: No signal · Safari: No signal |
| Spec | CSS Selectors Level 4 §user-action pseudos |
| ChromeStatus | 6296574159355904 — 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.
what changes
| Pseudo-class | Before Chrome 148 | After Chrome 148 |
|---|---|---|
:hover | Matched all ancestors up to <html>, even through dialog/popover | Stops propagating at the top-layer boundary |
:active | Same — could activate styles in backdrop page | Stops at top-layer boundary |
:focus-within | Could match the document root when focus was inside a dialog | Stops at top-layer boundary |
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
| Chrome | 148 — now spec-compliant |
|---|---|
| Firefox | No signal |
| Safari | No signal |