RESOLVED FIXED298514
Enable scroll anchoring (scroll position jumps when DOM height decreases above the viewport)
https://bugs.webkit.org/show_bug.cgi?id=298514
Summary Enable scroll anchoring (scroll position jumps when DOM height decreases abov...
karesz.carco
Reported 2025-09-07 14:53:47 PDT
# Bug Report: Safari scroll position jumps when DOM height decreases above the viewport (React/JS apps) **Product:** WebKit (Safari, iOS & macOS) **Component:** Scrolling / Scroll Anchoring **Version:** Latest stable Safari on macOS and iOS (2025) **Reproducible:** Always --- ## Description When the document or a scroll container **loses height above the current viewport position** (e.g. an item is removed from a list, or an image is deleted at the bottom while the user is scrolled to the end), Safari unexpectedly **jumps the scroll position upward**. Other browsers (Chrome, Firefox, Edge) correctly preserve the user’s visual position, thanks to proper **scroll anchoring** (`overflow-anchor`). Safari’s lack of consistent scroll anchoring support makes the problem reproducible across many webapps. This affects modern React applications (and other JS frameworks) where UI updates often change DOM height dynamically. --- ## Steps to Reproduce 1. Create a scrollable list in Safari with enough content to fill >2× the viewport height. 2. Scroll to the very bottom. 3. Programmatically remove an item from the list near the bottom (e.g. `setState` → React re-renders → `scrollHeight` decreases). 4. **Observed:** the scroll position jumps upward instead of staying at the bottom. --- ## Expected Behavior - The user should remain at the same **visual position** (anchored). - If scrolled to the very bottom, the viewport should stay “stuck” to the bottom after the DOM shrinks. - This is what Chromium and Firefox implement with scroll anchoring. --- ## Actual Behavior in Safari - Scroll position jumps upwards when content above/below is removed. - Momentum scrolling makes the issue worse — when removing content while a scroll animation is ongoing, the viewport “snaps” to unexpected positions. - On iOS Safari, the effect is very visible in chat UIs, galleries, or forms that add/remove images. --- ## Related Issues / References - **WebKit Bugs** - [171099 – Scroll Anchoring not implemented](https://bugs.webkit.org/show_bug.cgi?id=171099) - [261692 – ScrollTop adjustments after DOM mutation not applied in same paint](https://bugs.webkit.org/show_bug.cgi?id=261692) - **React community reports** - [react-window #122](https://github.com/bvaughn/react-window/issues/122) – Safari momentum scroll issues - [react-virtuoso #945](https://github.com/petyosi/react-virtuoso/issues/945) – Glitches on iOS Safari when items mount/unmount - [StackOverflow: Safari scroll jump after unloading element](https://stackoverflow.com/questions/78873165/safari-scroll-jump-after-unloading-element-innerhtml) - [Reddit ReactJS thread](https://www.reddit.com/r/reactjs/comments/z73twz/screen_jumping_around_when_some_dom_elements_get/) --- ## Workarounds Developers Use - **Delta correction with ResizeObserver:** measure `oldScrollHeight - newScrollHeight` and adjust `scrollTop` manually. - **Double `requestAnimationFrame`:** wait for layout to settle before correcting. - **`overflow-anchor: none;`** on containers, combined with manual anchoring logic (no effect in Safari stable, but works in Chromium/Firefox). - **Avoid margins / unknown heights:** using `padding` or `aspect-ratio` to stabilize layout shifts. These hacks are widely implemented in libraries (`react-window`, `react-virtualized`, `react-virtuoso`) but add unnecessary complexity. --- ## Why This Matters - Affects **millions of webapps** where users scroll through dynamic content (chats, feeds, galleries, forms). - The issue **breaks user expectation**: when you delete an image at the bottom, you want to stay at the bottom — Safari jumps away. - Developers are forced to add fragile, JS-heavy hacks that could be avoided with proper scroll anchoring implementation. --- ## Suggested Resolution - Implement **full scroll anchoring** as per the spec. - Apply anchoring consistently when `scrollHeight` decreases above the viewport, even during momentum scroll. - Align behavior with Chromium/Firefox for web compatibility.
Attachments
test on chrome (android) (704.64 KB, video/mp4)
2025-09-08 04:31 PDT, karesz.carco
no flags
test on safari (ios) (2.16 MB, video/mp4)
2025-09-08 04:32 PDT, karesz.carco
no flags
Alexey Proskuryakov
Comment 1 2025-09-07 17:53:52 PDT
Thank you for the report. Could you please attach a test case? The report is very long and AI generated, with many incorrect statements made by the AI, making it quite unclear what exactly it is about.
karesz.carco
Comment 2 2025-09-08 04:29:14 PDT
In Safari, when the page height temporarily shrinks and then grows again (for example, when async data is removed and then re-inserted), the scroll position is not properly maintained. Other browsers preserve the scroll offset correctly. We used AI to help collect and summarize related issues, but we have actually been struggling with this for years. We believe this problem is heavily underrepresented, so we tried to provide a broader context showing that these height-change + scroll position bugs are a significant issue in mobile web apps. The attached CodePen reproduces the issue. Please note: in a real-world complex application this kind of height change can happen in many different situations. The demo is only one simplified example of when the page size changes and the scroll offset is lost. I also uploaded two videos: one shows Safari’s behavior, the other Chrome’s. Chrome (and all other browsers) correctly follow the updated page height when restoring the scroll position, but Safari fails to do so. Steps to reproduce in the demo: Scroll to the “Update” button. Press “Update (full refresh)”. The async section is removed (page shrinks), then re-appears after a short delay (page grows). Safari fails to follow the delayed height change, while Chrome correctly adjusts the scroll offset. https://codepen.io/K-roly/pen/EaVModM
karesz.carco
Comment 3 2025-09-08 04:31:17 PDT
Created attachment 476672 [details] test on chrome (android)
karesz.carco
Comment 4 2025-09-08 04:32:44 PDT
Created attachment 476673 [details] test on safari (ios)
Simon Fraser (smfr)
Comment 5 2025-09-08 12:25:23 PDT
Simon Fraser (smfr)
Comment 6 2025-09-08 12:25:52 PDT
We can use this bug to track enabling scroll-anchoring. We have an implementation, but it has some issues with async scrolling.
Simon Fraser (smfr)
Comment 7 2026-03-27 10:55:20 PDT
Simon Fraser (smfr)
Comment 8 2026-03-27 10:55:58 PDT
EWS
Comment 9 2026-03-27 15:13:34 PDT
Committed 310113@main (3727113a63a7): <https://commits.webkit.org/310113@main> Reviewed commits have been landed. Closing PR #61508 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.