Scroll-driven animations are Baseline at last

Scroll-driven animations are Baseline at last

This note has an interactive demo. Try it in the original Reading progress bars, cards that slide in as they appear, a hero that fades while you scroll past it: all of that can now be plain CSS in every major browser. Firefox 159 shipped on October 27, 2026 with scroll-driven animations enabled by default, and that same day the feature became Baseline. In the demo above, scroll inside the panel: the bar, the percentage, the 3D ring and the cards all follow your scroll, and there isn't a single scroll listener in the page. What changes A normal CSS animation runs on the document timeline: it moves from the first keyframe to the last as time passes. Scroll-driven animations swap that clock for a different one with the animation-timeline property. There are two kinds of timeline: Scroll progress timeline, with scroll(): progress goes from 0% to 100% as a scroll container scrolls from top to bottom. View progress timeline, with view(): progress depends on how far an element (the subject) has travelled through the visible area of its scroll container. You keep writing the same @keyframes you already know. What changes is what drives them. And because it's declarative, you don't need scroll events, requestAnimationFrame or an IntersectionObserver to sync anything. How it works The progress bar at the top of the demo is the classic example: .progress { transform-origin: 0 50%; transform: scaleX(0); animation: grow 1ms linear both; animation-timeline: scroll(nearest block); /* after the shorthand */ } @keyframes grow { to { transform: scaleX(1); } } Enter fullscreen mode Exit fullscreen mode scroll() takes two optional arguments: which scroller to use (nearest, the default; root for the document; or self) and which axis (block by default, or inline, x, y). Two details in that block matter: The order. The animation shorthand resets animation-timeline to auto, but it can't set it. MDN says it plainly: declare animation-timeline after any animation shorthand, or it won't take effect. The 1ms. On a scroll timeline the duration doesn't control anything, but according to MDN, Firefox needs a non-zero animation-duration to apply the animation. That's why 1ms is the common convention. The cards use view(), and animation-range decides which stretch of their journey the animation happens in: .card { animation: reveal 1ms linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; } @keyframes reveal { from { opacity: 0; transform: translateY(60px) rotateX(-55deg) scale(.86); } to { opacity: 1; transform: none; } } Enter fullscreen mode Exit fullscreen mode The spec defines named ranges for a view timeline. cover is the whole journey, from the moment the element starts to enter until it has completely left. contain is the stretch where it's fully inside the visible area. entry and exit are the stretches where it's entering and leaving. The buttons at the top of the demo switch between entry, cover 0% cover 50% and contain. With the same scroll position, the same card ends up at a different opacity, because each range maps that position to a different point in the animation. You can also give a timeline a name and use it from another element. The panel declares scroll-timeline: --page block, and the 3D ring and the counter use animation-timeline: --page. The counter is a little trick: an integer registered with @property, animated from 0 to 100 and printed with counter(). The percentage you see is computed by the browser while you scroll. From JavaScript you get the same timeline. This is the line that feeds the readout in the demo: const timeline = new ScrollTimeline({ source: viewport, axis: 'block' }); timeline.currentTime; // CSSUnitValue in percent, e.g. 42% Enter fullscreen mode Exit fullscreen mode The spec defines currentTime as a percentage CSSUnitValue, and as null when the timeline is inactive. Browser support and gotchas Support: Chrome and Edge 115, Safari 26 (the release notes say "Added support for Scroll-driven Animations") and Firefox 159. According to the web-features data, it has been Baseline "newly available" since October 27, 2026. Anyone who hasn't updated still won't see it, so detect it: the demo checks CSS.supports('animation-timeline: scroll()') and, if that fails, shows a notice and uses a JavaScript fallback with a scroll listener and an IntersectionObserver. In CSS, the equivalent is @supports (animation-timeline: scroll()). overflow: hidden creates a scroller. This one caught me while building the demo. The bar's track had overflow: hidden to round its corners, and in Chromium the bar stayed at zero. MDN's definition explains why: hidden turns an element into a scroll container, so scroll(nearest) was finding the track (which doesn't scroll) instead of the panel. Switching to overflow: clip fixed it, because clip doesn't create a scroll container. The shorthand doesn't set the timeline. In MDN's compatibility data, animation-timeline as part of animation is only "reset-only" in Chromium and not supported in Firefox or Safari. Always write it as its own declaration. Motion still needs a switch. MDN reminds you to respect prefers-reduced-motion. In the demo, with reduced motion on, the ring and the hero text stop moving and the cards only fade in, with no 3D rotation. The progress bar stays, because it doesn't move anything across the screen. What to keep an eye on "Widely available" status. Baseline "newly available" means every engine ships it, not that every user has updated. Keep the fallback for a while. Your scroll libraries. If you load a library only for progress bars or reveal-on-scroll effects, it's worth checking how much of it CSS now covers. The spec is still an Editor's Draft. The CSSWG document is marked as "revising" and still has open issues, for example about what 0% means for some scroll containers. The basics shown here work today in all three engines, but there are still details to settle. Sources animation-timeline – MDN (source on GitHub) Scroll-driven animation timelines – MDN guide (source on GitHub) Firefox 159 release notes for developers – MDN (source on GitHub) Safari 26 release notes – Apple Developer Scroll-driven Animations, Editor's Draft source – CSS Working Group Originally published at richi.codes.

Original Source

Read the full article at Dev →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.