Skip to content

fix(review): work around Safari scroll-reset bug with shadow DOM diffs#547

Merged
backnotprop merged 1 commit intomainfrom
fix/scroll-safari
Apr 12, 2026
Merged

fix(review): work around Safari scroll-reset bug with shadow DOM diffs#547
backnotprop merged 1 commit intomainfrom
fix/scroll-safari

Conversation

@backnotprop
Copy link
Copy Markdown
Owner

Summary

  • Works around a Safari/WebKit compositor bug where scrollTop resets to 0 when momentum-scrolling ends inside a scroll container with a <diffs-container> shadow DOM child
  • Adds a WebKit-only scroll event listener that detects bogus resets (scrollTop jumping from >200 to 0 in a single event) and synchronously restores the last known good position
  • Zero cost on Chrome/Firefox/Edge — the listener is never attached outside WebKit

Root cause

Safari's compositor loses track of scroll position when a web-component shadow DOM (@pierre/diffs <diffs-container>) is the child of a scroll container. The reset bypasses all JavaScript APIs — intercepting scrollTo() and the scrollTop setter caught zero calls. Confirmed via systematic elimination:

  1. Not OverlayScrollbars — bug persists with a plain <div style="overflow:auto">
  2. Not the CSS layout — a static tall div scrolls fine in the same flex container
  3. Not any JS code — intercepting scrollTo and scrollTop setter caught nothing
  4. It IS @pierre/diffs — removing the <diffs-container> shadow DOM fixes scrolling

Test plan

  • Open a code review with a large diff in Safari — scroll down with trackpad momentum, verify position is maintained
  • Scroll up to the top in Safari — verify it reaches the top normally without being blocked
  • Switch files in the file tree while scrolled down — verify new file starts at the top
  • Verify scrolling works normally in Chrome/Firefox (guardian is inactive)

Closes #540

#540)

Safari's compositor resets scrollTop to 0 when momentum-scrolling ends
inside a container whose child is a web-component shadow DOM (the
@pierre/diffs `<diffs-container>`). The reset bypasses all JavaScript
APIs — neither scrollTo nor the scrollTop setter fires.

Add a WebKit-only scroll event listener that detects the bogus reset
(scrollTop jumping from >200 to 0 in a single event, which cannot
happen during normal scrolling) and synchronously restores the last
known good position before the browser paints the wrong frame.

Closes #540

For provenance purposes, this commit was AI assisted.
@backnotprop backnotprop merged commit aa73295 into main Apr 12, 2026
7 checks passed
@backnotprop backnotprop deleted the fix/scroll-safari branch April 12, 2026 23:55
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.

Scrolling the diff jumps back to the top in Safari

1 participant