Background Scroll Not Locked When Modal Is Open
When a modal, drawer, or overlay opens in your application, the background page continues to scroll on mobile devices. Users scrolling within the modal accidentally scroll the page behind it, losing their place. When the modal closes, the page has scrolled to a completely different position.
This is one of the most noticeable mobile UX bugs. It makes modals feel broken, confuses users, and creates a jarring experience. The issue is particularly bad on iOS Safari, which has unique scroll behavior that makes standard CSS solutions insufficient.
Claude Code typically generates modals that work well on desktop (where body overflow: hidden is sufficient) but break on mobile where touch scroll events propagate differently through the DOM.
Error Messages You Might See
Common Causes
- Only setting overflow: hidden on body — This works on desktop but iOS Safari ignores it for touch-initiated scrolls
- Missing position: fixed on body — Without fixing the body position, iOS allows the viewport to scroll behind overlays
- Scroll position lost on lock — Setting position: fixed resets scroll position to top; it's not restored when the modal closes
- Touch events not prevented — Touchmove events on the overlay backdrop propagate to the body
- Nested scrollable content — A scrollable area inside the modal (like a long form) conflicts with scroll prevention on the body
How to Fix It
- Use a battle-tested library — Install body-scroll-lock or use React's createPortal with scroll management from Radix UI or Headless UI
- Save and restore scroll position — Before locking, save window.scrollY. Set body to position: fixed; top: -scrollY. On unlock, restore scrollTo(0, scrollY)
- Handle iOS Safari specifically — Add -webkit-overflow-scrolling: touch to the modal content and prevent touchmove on the backdrop
- Use the dialog element — The native HTML dialog element with showModal() handles scroll locking correctly in modern browsers
- Test on real iOS devices — iOS Safari scroll behavior cannot be accurately tested in Chrome DevTools mobile simulation
Real developers can help you.
You don't need to be technical. Just describe what's wrong and a verified developer will handle the rest.
Get HelpFrequently Asked Questions
Why doesn't overflow: hidden work on iOS Safari?
iOS Safari handles touch scroll events differently from desktop browsers. Setting overflow: hidden on the body doesn't prevent touch-initiated scrolling. You need to also set position: fixed and manage the scroll position manually.
What's the simplest cross-browser scroll lock solution?
Use the body-scroll-lock npm package or the native HTML dialog element with showModal(). Both handle cross-browser scroll locking including iOS Safari edge cases.