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: none removes 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 scroll event does not indicate why scrolling occurred
    • user gestures, keyboard input, drag-based auto-scrolling, and programmatic scrolling are effectively indistinguishable at the event level
  • 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
    • should prefer native scrolling over scroll-jacked effects
  1. 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.