Scrolling
Field notes on scroll behaviour and scroll-driven code. Recommended read: Cheng Lou’s scrolling document.
- on macOS and iOS, rubber-banding creates an elastic overscroll effect that gently communicates the end of content without interrupting input
- it’s primarily an Apple-platform UI affordance, supported by Safari and Firefox for both page-level and container scrolling1
- Chrome applies elastic bounce to the page, not to scrollable containers
- disabling it with
overscroll-behavior: noneremoves boundary feedback (generally not recommended) - suppressing elastic overscroll removes an important boundary signal, which can make interactions that rely on continuous input (such as scrubbing or drag-based controls) feel abruptly clipped
- scroll affordances often double as input feedback
- elastic resistance, momentum decay, and boundary feedback are frequently reused by users as cues for fine-grained control, even when the interaction is not strictly scrolling
- scrolling is often handled off the main thread, on the compositor, so it remains smooth even under JavaScript work
- scroll events provide no provenance regarding their source
- a
scrollevent does not indicate why scrolling occurred - user gestures, keyboard input, drag-based auto-scrolling, and programmatic scrolling are effectively indistinguishable at the event level
- a
- Apple scrolling physics feel like momentum with gentle decay
- most attempts to reproduce this behaviour feel noticeably off
- off-main-thread scrolling preserves perceived smoothness but limits the reliability of scroll-driven JavaScript effects
- this trade-off is a constraint of current browser engines
shouldprefer native scrolling over scroll-jacked effects
- Browser support varies by engine and platform. On iOS, all browsers are WebKit and inherit elastic overscroll behaviour. On macOS, Chrome and Firefox can integrate with OS-level scrolling physics, but their behaviour differs for overflow containers and isn’t consistent across engines.