af-utils icon indicating copy to clipboard operation
af-utils copied to clipboard

@af-utils/scrollend-polyfill: scrollend event firing too early when user stops scrolling but keeps finger/trackpad contact

Open mbohgard opened this issue 4 months ago • 0 comments

Description

When a user scrolls using a touchscreen or trackpad, the polyfill dispatches a scrollend event as soon as the scroll position stops changing, even if the user’s finger or trackpad gesture is still active.

In contrast, the native scrollend event in Chrome and Firefox fires after the scroll gesture fully completes — that is, when the user lifts their finger or ends the input sequence (including momentum scrolling).

This results in the polyfill reporting a “scroll end” too early, while the user is still in control of the gesture.


🧩 Steps to Reproduce

  1. Use the Scrollyfills polyfill on Safari (or another browser without native scrollend).

  2. Add a listener:

    window.addEventListener('scrollend', () => console.log('scrollend fired'));
    
  3. Scroll a container (or the page) using:

    • a trackpad, or
    • a touchscreen.
  4. Stop movement briefly but keep your finger or trackpad contact active — don’t release yet.


❌ Actual Behavior

  • The polyfill dispatches scrollend immediately after scroll motion stops, even though the gesture is still active.
  • If the user then resumes scrolling without lifting their finger, multiple premature scrollend events may fire within the same gesture.

✅ Expected Behavior

  • scrollend should fire only after the user has finished the gesture, i.e. after:
    • the final scroll motion has stopped and
    • the finger or trackpad contact has ended (touchend / mouseup).
  • The event should also fire once inertial (momentum) scrolling ends.

This matches native scrollend behavior in Chrome/Firefox.


💡 Notes / Ideas

  • The polyfill currently seems to rely solely on scroll position stability to infer “scroll end.”
  • It should consider combining that with gesture-end events (touchend, mouseup) to ensure the user has actually released the scroll interaction.
  • Chrome’s native implementation delays scrollend until the full scroll transaction (including momentum) is over.

🧰 Environment

  • Browser: Safari 26.0.1 (macOS)
  • Polyfill: @af-utils/scrollend-polyfill v0.0.14
  • Device: MacBook trackpad

🧠 Why this matters

Without this distinction, scroll-driven UIs (e.g., scroll snapping or scroll-triggered animations) may re-enable snapping or trigger transitions while the user is still interacting, resulting in janky or conflicting UX compared to browsers with native scrollend.

mbohgard avatar Nov 12 '25 13:11 mbohgard