NEW 246048
Incorrect scroll position reported
https://bugs.webkit.org/show_bug.cgi?id=246048
Summary Incorrect scroll position reported
Jack Doyle
Reported 2022-10-04 16:19:36 PDT
Simple test case: https://codepen.io/GreenSock/pen/VwxxwWm?editors=0010 Scroll on any iOS device relatively quickly up and down. Notice the blue bar bounces around like crazy rather than staying "stuck". The scroll position seems to be incorrectly reported or rendering is happening out-of-sync. Challenge: can you please recommend a way to keep the blue bar "stuck" using transforms? I can't use something like position: fixed because the container may have a transform applied. sticky isn't an option either. I need a way to get the correct scroll position and apply it at the correct time to make that element appear frozen while scrolling its container. Help?! I've reached out directly to the Safari team at least 5 times over the past few months and never receive an answer, so I'm posting a bug report here. I have no idea if these are related to this issue, but here are several other reduced test cases showing various scroll-related bugs/inconsistencies in iOS Safari: - https://codepen.io/GreenSock/pen/XWajYwG/16c435b12ef09c38125204818e7b45fc - https://codepen.io/GreenSock/pen/ExbrPNa/087cef197dc35445a0951e8935c41503 - https://codepen.io/GreenSock/pen/JjOxYpQ/3dd65ccec5a60f1d862c355d84d14562
Attachments
Simon Fraser (smfr)
Comment 1 2022-10-04 17:08:16 PDT
It's currently not possible to position an element in JavaScript in a way that is frame-accurate with user scrolling. Scrolling on iOS is always asynchronous.
Jack Doyle
Comment 2 2022-10-04 17:14:03 PDT
Dang! Okay, "currently not possible..." does that mean that may change sometime soon? [fingers crossed] And can you think of any out-of-the-box strategies to somehow make this work?
Simon Fraser (smfr)
Comment 3 2022-10-04 17:22:20 PDT
The only way would be to use position:fixed or position:sticky. Can you hoist your fixed thing outside the transformed ancestor?
Jack Doyle
Comment 4 2022-10-04 22:16:09 PDT
Unfortunately, no, that isn't possible. We don't have control over the markup/structure. There aren't any tricks to getting scroll to be synchronous? I attempted to preventDefault() on touchmove events and handle the scrolling via JavaScript which should totally work in theory, but there's a nasty bug in iOS Safari since 2018 (from what I can tell) that makes it impossible because the event.clientY/X are incorrectly reported, as illustrated in one of my demos provided: https://codepen.io/GreenSock/pen/ExbrPNa/087cef197dc35445a0951e8935c41503 That bug report is here: https://bugs.webkit.org/show_bug.cgi?id=181954 I tried bumping it months ago and got no answer. So I have no way of figuring out where the user's finger actually is in the viewport (reliably) when scroll is involved. Or am I missing something?
Radar WebKit Bug Importer
Comment 5 2022-10-11 16:20:17 PDT
Simon Fraser (smfr)
Comment 6 2024-11-04 20:26:21 PST
There are a number of data races that cause the web process scroll position to be stale relative to the UI process. In the following, {} represents some asynchronous behavior, and newlines represent thread or process hop. A page render is triggered via : CADisplayLink -> RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay -> IPC -> RemoteLayerTreeDrawingArea::displayDidRefresh -> { zero delay timer } -> Page::updateRendering() A scroll update getting to the web process goes via: UIScrollView -> { Core Animation pre-commit hook } -> -[WKContentView didUpdateVisibleRect:] -> IPC -> ViewUpdateDispatcher work queue -> -> ViewUpdateDispatcher::visibleContentRectUpdate There are two main races here. The RemoteLayerTreeDrawingArea::displayDidRefresh message may reach the web process before the ViewUpdateDispatcher::visibleContentRectUpdate, and the ViewUpdateDispatcher work queue can delay the visibleContentRectUpdate getting to the main thread. For everything to work correctly, the new scroll position from UIScrollView needs to get into a visibleContentRectUpdate before Page::updateRendering() runs. That rarely happens.
Note You need to log in before you can comment on or make changes to this bug.