Skip to content

Fix scroll-driven opacity broken in Safari & Firefox#3587

Open
mattgperry wants to merge 1 commit intomainfrom
worktree-fix-issue-3559
Open

Fix scroll-driven opacity broken in Safari & Firefox#3587
mattgperry wants to merge 1 commit intomainfrom
worktree-fix-issue-3559

Conversation

@mattgperry
Copy link
Collaborator

Summary

  • Replace simple window.ScrollTimeline !== undefined existence check with a runtime test that verifies scroll-driven opacity actually works
  • Gate supportsViewTimeline() on the same check since ViewTimeline shares the same rendering engine
  • Add Cypress E2E test for scroll-driven opacity animation

Problem

Safari and Firefox expose window.ScrollTimeline but their implementations have bugs with non-transform properties like opacity:

  • Safari: opacity stays at an intermediate value even after scrolling past the animation endpoint
  • Firefox: opacity jumps to full immediately with no gradual transition

scale and rotate transforms work correctly in both browsers. The issue is specifically with non-transform CSS properties driven by scroll timelines via WAAPI.

Fix

The supportsScrollTimeline() check now creates a tiny off-screen scrollable element, attaches a scroll-driven opacity animation, scrolls to the end, and verifies the computed opacity is correct (~1.0). This runs once (memoized) and automatically adapts as browsers fix their implementations.

In browsers where the test fails (Safari, Firefox currently), the library falls back to the JS-based scroll tracking path which correctly drives all CSS properties.

Fixes #3559

🤖 Generated with Claude Code

supportsScrollTimeline() only checked window.ScrollTimeline existence.
Safari and Firefox expose the API but have bugs with non-transform
properties (opacity stays intermediate in Safari, jumps to final value
in Firefox). Replace the simple existence check with a runtime test
that creates a scroll-driven opacity animation and verifies the
computed value is correct. Also gate supportsViewTimeline() on the
same check since it shares the underlying rendering engine.

Fixes #3559

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link

greptile-apps bot commented Mar 3, 2026

Greptile Summary

Replaced naive window.ScrollTimeline !== undefined check with a runtime test that actually verifies scroll-driven opacity animations work correctly. The fix addresses Safari and Firefox exposing the ScrollTimeline API but having broken implementations for non-transform properties.

Key Changes:

  • Runtime test creates an off-screen scrollable element, applies scroll-driven opacity animation, scrolls to end, and verifies computed opacity reaches ~1.0
  • Test is memoized for performance and will automatically adapt as browsers fix their implementations
  • supportsViewTimeline() now depends on supportsScrollTimeline() since both use the same rendering engine
  • Comprehensive Cypress E2E tests verify opacity 0→1 progression and scale transforms work alongside opacity

The fix follows repository guidelines: includes proper E2E tests with test page in dev/react/src/tests/ and spec in cypress/integration/, correctly places implementation in framework-agnostic motion-dom package, and uses concise code patterns.

Confidence Score: 5/5

  • This PR is safe to merge with no risk
  • Score reflects thorough testing (Cypress E2E), clean implementation with proper error handling, correct fix for a well-documented browser bug, and follows all repository guidelines
  • No files require special attention

Important Files Changed

Filename Overview
packages/motion-dom/src/utils/supports/scroll-timeline.ts Replaced simple existence check with runtime test that verifies scroll-driven opacity actually works, correctly handling Safari/Firefox bugs
dev/react/src/tests/scroll-opacity-native.tsx Added test page for scroll-driven opacity/scale animations using useScroll and useTransform
packages/framer-motion/cypress/integration/scroll-opacity-native.ts Added Cypress E2E tests verifying opacity animates 0→1 on scroll and scale transforms work correctly

Last reviewed commit: 58b5432

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.

[BUG] useScroll + useTransform opacity broken in Safari & Firefox since ScrollTimeline adoption (~12.30+)

1 participant