Preventing scroll chaining without JavaScript
When a scrollable element inside a modal reached its end, scroll would chain to the page behind it. The fix was a JS wheel event listener calling e.preventDefault(). overscroll-behavior: contain stops that natively.
2 overflow-y: auto;
3 overscroll-behavior: contain;
4}
2// JS: prevent scroll chaining on wheel and touch
3modal.addEventListener('wheel', (e) => {
4 e.preventDefault();
5}, { passive: false });
6// also needed for touch: touchmove listener
This feature is well established and works across many devices and browser versions. It has been available across browsers since 2022.
No JavaScript
No wheel or touchmove event listener, no preventDefault, no passive flag concerns.
Works on touch too
Handles touch scroll chaining on mobile without the complexity of non-passive event listeners.
Pull-to-refresh too
overscroll-behavior: none also prevents pull-to-refresh on Chrome Android for full-screen app-like layouts.
How it works
Scrollable panels inside modals or dropdowns would chain scroll to the page once the panel reached its end. Stopping this required non-passive wheel and touchmove event listeners calling e.preventDefault(), which also blocked the browser's scroll optimizations and required separate handling for touch.
overscroll-behavior: contain stops scroll propagation at the element's boundary. The inner element scrolls normally, but the chain ends there. overscroll-behavior: none additionally prevents the bounce effect and pull-to-refresh on supported platforms.