demo · v140
Overscroll Recipe Book
Four real-world patterns that rely on overscroll-behavior being set on :root or html and propagating to the viewport. Before Chrome 140 that propagation was broken — these patterns silently failed.
No pull-to-refresh in a PWA
A standalone PWA must suppress the pull-to-refresh gesture. html { overscroll-behavior-y: none; } is the one-liner — but it only propagates to the viewport in Chrome 140+.
Scroll me. Overscroll at the top — pull-to-refresh is suppressed.
This simulates html { overscroll-behavior-y: none; } propagated to the viewport.
The overscroll-behavior-y: none is applied to this frame to show the effect.
In the Chrome 138 simulation below, the root-level setting does nothing.
End of scrollable content.
/* works as of Chrome 140 */
html { overscroll-behavior-y: none; }
Scroll-linked animation progress bar
A progress bar that fills as you scroll. Uses overscroll-behavior-y: none on root so elastic overscroll doesn't jerk the animation past 100%.
Scroll down to animate the progress bar above. With Chrome 140 the bar stays clamped to 100% — no overscroll overshoot.
Paragraph two. Scroll further.
Paragraph three. Keep going.
Paragraph four.
Paragraph five.
Paragraph six — you're near the end.
Paragraph seven — bottom of content.
html { overscroll-behavior-y: none; }
/* scroll-driven animation then reads clean scroll position */
@keyframes grow { from { transform: scaleX(0) } to { transform: scaleX(1) } }
#progress-bar { animation: grow linear; animation-timeline: scroll(root); }
Lock scroll while modal is open
When a modal dialog is open, background scroll should be locked. Toggle overscroll-behavior: contain on the body via a class, now that root propagation works.
/* on modal open */
document.documentElement.style.overscrollBehavior = "none";
/* on modal close */
document.documentElement.style.overscrollBehavior = "";
Custom pull-to-refresh indicator
Suppress the browser's built-in pull-to-refresh with overscroll-behavior-y: none on root, then show a custom indicator when the user drags down past the top.
html { overscroll-behavior-y: none; }. Developers had to add the rule to body as a workaround.Scroll to the top of the frame below, then click "Simulate overscroll" to trigger the custom indicator:
Content item 1 — scroll to top and overscroll to trigger custom PTR.
Content item 2.
Content item 3.
Content item 4 — bottom of content.
html { overscroll-behavior-y: none; }
window.addEventListener("touchstart", e => {
if (window.scrollY === 0) startCustomPTR();
});
see also
- Viewport Overscroll Propagation — feature index
- Standalone PWA — sibling concept
- ChromeStatus entry
- CSS Overscroll Behavior Level 1