Stop the page scrolling behind an open popup
Add body:has(dialog[open]) { overflow: hidden; } and the page stays still while a dialog is open, then scrolls again when it closes. No JavaScript needed.
The code
body:has(dialog[open]) {
overflow: hidden;
}dialog[open] matches the browser's own <dialog> element. If your popup comes from a plugin or page builder, swap in the class it adds when it opens, for example body:has(.modal.is-open).
Some themes scroll on html, not body. If the page still moves, put the same rule on html.
Tested
: in Chromium (through Playwright). With a dialog open, three 400 px scroll-wheel moves over the backdrop scrolled the page 1,200 px. With the rule the page stayed at the top. After the dialog closed, the same scroll moved it 1,200 px again. Not yet checked on a real iPhone, where Safari has a history of scroll quirks.
Browser support
:has() works in Chrome and Edge 105+, Safari 15.4+ and Firefox 121+. Sources: MDN: :has(), Can I use: :has(), MDN: the dialog element.
Transcript
Your page shouldn't scroll behind an open popup. One line of CSS stops it. Let me show you how.
Popup open, I scroll, and the whole page slides about underneath.
Here's the trick. CSS can now check what's inside an element, using has. So the body gets overflow hidden, but only when it has an open dialog. Close the popup and it scrolls again.
No JavaScript. Chrome, Safari, Firefox and Edge all support it.
I've added a link to this line in the comments below.
On screen: a test page with a "Book a free check" dialog open and the page sliding about behind it. Then a code editor showing body:has(dialog[open]) { with the pointer on :has(, the same dialog with the page staying still, and the page scrolling again after the dialog closes. The address bar reads yourwebsite.co.uk.
The presenter in the video is an AI avatar made in HeyGen, speaking with a clone of Jamie's voice. The script, demo and test were made by ELK Digital with Claude.