Skip to content

fix(gallery): subpixel scroll stall + scroll resync + resize remeasure - #34

Open
Faych (neverbiasu) wants to merge 1 commit into
microsoft:mainfrom
neverbiasu:fix/gallery-marquee
Open

fix(gallery): subpixel scroll stall + scroll resync + resize remeasure#34
Faych (neverbiasu) wants to merge 1 commit into
microsoft:mainfrom
neverbiasu:fix/gallery-marquee

Conversation

@neverbiasu

Copy link
Copy Markdown
Contributor

Summary

Fix the marquee stall caused by Chrome subpixel scrollLeft rounding in the gallery carousels.

This patch keeps the auto-scroll phase continuous while still allowing user-driven manual scrolls to resync cleanly after pointer/touch/wheel interaction. It also re-measures loop periods on resize without duplicating content again.

Root cause

Chrome rounds subpixel scrollLeft values to integers during DOM writes. When the marquee loop keeps updating from a stale phase, the next frame can effectively write 0.4px or 0.45px, which Chrome rounds to 0, causing the carousel to appear stuck.

What changed

  • docs/idea-page/gallery.js

    • keeps a tracked _lastWritten value for the last DOM write
    • resyncs phase when user scrolls manually
    • avoids stale closure state by looking up state by track element
    • re-measures singleWidth on resize without duplicating content again
  • docs/reel-page/gallery.js

    • same fix pattern for the reel wall marquee
    • re-measures loop period on resize
    • keeps loop state synchronized to the actual scrollLeft value

Files changed

  • docs/idea-page/gallery.js
  • docs/reel-page/gallery.js

Verification

  • Verified in browser that both carousels continue scrolling smoothly without stalling
  • Manual scroll resync works: after user-driven scroll, the loop resumes from the current position without snapping backward
  • Scope is limited to the two gallery files relative to upstream/main

Notes

This is a follow-up to the earlier marquee ping-pong fix that was already merged upstream. This PR specifically addresses the remaining subpixel/rounding stall issue.

Chrome rounds subpixel scrollLeft writes to the nearest integer, so writing
0.4/0.45px directly rounds to 0 every frame and the marquee stalls. Keep the
fractional position in a floating-point phase accumulator and only write the
integer part to scrollLeft.

- phase accumulator: s.phase += SPEED * dir; write Math.round(s.phase)
- manual-scroll resync: scroll listener compares against the last written
  value and resyncs the phase on user scrolls (arrows, touch, wheel)
- resize remeasurement: setup is idempotent (dataset.looping guard), re-measures
  the loop period and re-syncs phase to the current position without
  duplicating content a second time
- retain main's updated 32px padding (no CSS changes)
- fix stale-state capture: listeners looked up state by closure, which broke
  hover-pause after resize re-ran setup; now look up by element
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant