Skip to content

Disable ScrollTimeline in Safari #33499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Jun 10, 2025

Stacked on #33501.

This disables the use of ScrollTimeline when detected in Safari in the recommended SwipeRecognizer approach. I'm instead using a polyfill using touch events on iOS.

Safari seems set to release ScrollTimeline soon. Unfortunately it's not really what you'd expect.

First of all, it's not running in sync with the scroll which is kind of its main point. Instead, it is running at 60fps and out of sync with the scroll just like JS. In fact, it is worse than JS because with JS you can at least spawn CSS animations that run at 120fps. So our polyfill can respond to touches at 60fps while gesturing and then run at 120fps upon release. That's better than with ScrollTimeline.

Second, there's a bug which interrupts scrolling if you start a ViewTransition when the element is being removed as part of that. The element can still respond to touches so in a polyfill this isn't an issue. But it essentially makes it useless to use ScrollTimeline with swipe-away gestures.

So we're better off in every scenario by not using it.

The UA detection is a bit unfortunate. Not sure if there's something more specific but we also had to do a UA detection for Chrome for View Transitions. Those are the only two we have in all of React.

safarimeme

@github-actions github-actions bot added the React Core Team Opened by a member of the React Core Team label Jun 10, 2025
@react-sizebot
Copy link

react-sizebot commented Jun 10, 2025

Comparing: a947eba...0923474

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB +0.05% 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 530.57 kB 530.57 kB = 93.67 kB 93.67 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB +0.11% 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.12% 651.66 kB 652.47 kB +0.15% 114.78 kB 114.96 kB
facebook-www/ReactDOM-prod.classic.js = 674.81 kB 674.81 kB = 118.78 kB 118.78 kB
facebook-www/ReactDOM-prod.modern.js = 665.30 kB 665.30 kB = 117.19 kB 117.19 kB

Significant size changes

Includes any change greater than 0.2%:

(No significant changes)

Generated by 🚫 dangerJS against 0923474

const supportsScrollTimeline =
typeof ScrollTimeline === 'function' &&
(ua.indexOf('Safari') === -1 ||
(ua.indexOf('iPhone') === -1 && ua.indexOf('iPad') === -1));
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of special casing iOS we might be able to deopt to the polyfill only if a touch event has happened before we start.

@sebmarkbage sebmarkbage force-pushed the disablesafariscrolltimeline branch 5 times, most recently from e0c0aba to 79d5399 Compare June 20, 2025 04:40
@sebmarkbage sebmarkbage force-pushed the disablesafariscrolltimeline branch from 79d5399 to 0923474 Compare June 20, 2025 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants