Scroll-driven animationsLimited availability
The animation-timeline, scroll-timeline, and view-timeline CSS properties advance animations based on the user's scroll position.
Not yet supported in all major browsers — check the table and provide a fallback.
Browser support
DesktopChrome
1–114Not supported
115+Supportedsince Jul 18, 2023
Current: 155Edge
12–114Not supported
115+Supportedsince Jul 21, 2023
Current: 154Firefox
✕Not supportedup to 157
Current: 157Safari
1–18.6Not supported
26+Supportedsince Sep 15, 2025
Current: 27MobileChrome Android
18–114Not supported
115+Supportedsince Jul 21, 2023
Current: 155Firefox Android
✕Not supportedup to 157
Current: 157Safari iOS
1–18.6Not supported
26+Supportedsince Sep 15, 2025
Current: 27How to use
Not supported in Firefox, Firefox Android. Use feature detection below and provide a fallback (or a polyfill) for those browsers.
Example
CSS
@keyframes grow {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
/* Reading progress bar driven by page scroll */
.progress {
transform-origin: left;
animation: grow linear;
animation-timeline: scroll(root);
}Feature detection
CSS · check before using
@supports (animation-timeline: scroll) {
/* styles that rely on animation-timeline: scroll */
}
/* or in JavaScript */
if (CSS.supports("animation-timeline", "scroll")) {
// use it
}Sub-features
Support for each part of the feature (37). The overall table above shows when the whole feature works.
| Sub-feature | Chrome | Edge | Firefox | Safari | Chrome Android | Firefox Android | Safari iOS |
|---|---|---|---|---|---|---|---|
| ScrollTimeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ScrollTimeline.ScrollTimeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ScrollTimeline.axis | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ScrollTimeline.source | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ViewTimeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ViewTimeline.ViewTimeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ViewTimeline.endOffset | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ViewTimeline.startOffset | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| ViewTimeline.subject | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-range | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-range-end | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-range-end.normal | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-range-start | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-range-start.normal | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-timeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-timeline.scroll | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation-timeline.view | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| animation.animation-timeline_included | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ | ✕ |
| scroll-timeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| scroll-timeline-axis | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
Show 17 more
| Sub-feature | Chrome | Edge | Firefox | Safari | Chrome Android | Firefox Android | Safari iOS |
|---|---|---|---|---|---|---|---|
| scroll-timeline-axis.block | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| scroll-timeline-axis.inline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| scroll-timeline-axis.x | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| scroll-timeline-axis.y | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| scroll-timeline-name | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| timeline-scope | 116 | 116 | ✕ | 26 | 116 | ✕ | 26 |
| timeline-scope.all | ✕ | ✕ | ✕ | 26 | ✕ | ✕ | 26 |
| timeline-scope.none | 116 | 116 | ✕ | 26 | 116 | ✕ | 26 |
| view-timeline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-axis | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-axis.block | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-axis.inline | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-axis.x | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-axis.y | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-inset | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-inset.auto | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |
| view-timeline-name | 115 | 115 | ✕ | 26 | 115 | ✕ | 26 |