CSS scroll-driven animations have been the spec that frontend developers have been quietly excited about for a couple of years, and in 2026 the browser support picture has finally shifted enough that teams are seriously considering shipping them. I’ve been watching this one closely. The syntax is genuinely clever, the possibilities are real, and the performance story is mostly good. But “mostly” is doing a lot of work in that sentence, and there are enough edge cases around accessibility and progressive enhancement to make a careless implementation properly painful.
Let me give you a clear-eyed look at what the spec actually does, where support stands for UK production audiences right now, and how to use it without breaking things for users who aren’t on Chrome 115+.

What CSS scroll-driven animations actually do
The traditional way to trigger an animation based on scroll position involved JavaScript: an IntersectionObserver, a requestAnimationFrame loop, or a library like GSAP’s ScrollTrigger. They work fine, but they run on the main thread, meaning scroll-linked visual effects can jank badly under load.
The CSS Scroll-Driven Animations spec, now a W3C standard, handles scroll progress entirely off the main thread. It introduces two new animation timeline types: ScrollTimeline, which ties animation progress to a scroll container’s position, and ViewTimeline, which tracks when an element enters and exits the viewport. You wire these up using the animation-timeline property, and the browser compositor handles the rest. No JavaScript required for the animation itself, which means no main-thread blocking, no dropped frames from a busy event loop.
A simple parallax header, a progress indicator at the top of a long article, a sticky navigation bar that transitions its opacity as you scroll, all of these become a handful of CSS declarations. For something like a reading progress bar, the code is almost insultingly short compared to the old approach. That’s genuinely exciting.
Browser support in 2026: the honest picture
According to Can I Use, CSS scroll-driven animations have strong support in Chromium-based browsers (Chrome, Edge, Opera, Samsung Internet) and are now shipping in Firefox 132+ without a flag. Safari is the sticking point. As of early 2026, Safari still lacks full support, sitting behind an experimental flag in the Technology Preview builds.
For UK production audiences this matters. According to Statcounter’s UK browser data, Safari on iPhone accounts for roughly 26-28% of mobile sessions in the UK, driven by Apple’s continued dominance in the British smartphone market. That’s not a negligible fraction you can wave away with a comment in the pull request. Desktop Safari is a smaller concern but still double digits among professional audiences, particularly in creative and publishing sectors.
My read: you can ship CSS scroll-driven animations in 2026, but you must treat them as a progressive enhancement, not a core experience requirement. If the animation’s absence degrades the page to something broken or confusing, that’s a design problem, not a browser support problem.

How to write it safely with @supports
The right pattern is to wrap any scroll-driven animation declarations in a feature query. @supports (animation-timeline: scroll()) returns true only in browsers that understand the property. Everything inside that block is ignored elsewhere. Your fallback state, meaning the non-animated version, should be the default, not an afterthought.
This is the same approach we’ve needed for years with container queries (which, as I covered in the container queries piece from earlier this year, finally reached a point where teams could confidently adopt them). The pattern is identical: define the base experience for everyone, layer the enhancement for capable browsers.
For the ViewTimeline use case specifically, think about what your element looks like when the animation hasn’t run. If a card fades in as it enters the viewport, it must start at full opacity in the fallback. An invisible card on Safari 17 is a content bug. Use animation-fill-mode: both carefully and always check the unsupported state manually.
The performance case, and where it breaks down
The off-main-thread execution story is real, but it has limits. Animating transform and opacity stays on the compositor and is fast. Animating layout-triggering properties like width, height, margin, or top forces reflow even in a scroll-driven context. The spec doesn’t magically make expensive properties cheap.
I’d also flag that tying many simultaneous animations to a single scroll container can still produce jank on lower-powered devices, particularly mid-range Android handsets. UK audiences skew more Android than many assume outside London; roughly 45% of UK mobile users are on Android according to Statcounter. Test on real mid-range hardware, not just a MacBook’s device emulator.
If your scroll-driven animation scenario is complex, it’s worth benchmarking against a well-optimised JavaScript approach. GSAP’s ScrollTrigger with will-change hints can still outperform a naive CSS implementation on cluttered pages. CSS scroll-driven animations win most of the time, but “most” again is doing work. For teams at agencies managing campaigns across multiple channels, where page performance is one piece of a larger conversion puzzle, vendors like dijitul Marketing will tell you that Core Web Vitals scores and visual flair need to coexist, not compete. A showy parallax effect that tanks your LCP score is a bad trade.
On the topic of performance and production readiness, I’d point you to the data in the UK Core Web Vitals piece we published earlier this year. The numbers there give useful context for how much headroom UK sites typically have before scroll-linked visual effects start eating into real performance budgets.
Accessibility: the part most tutorials skip
This is where I see the most careless implementations. The prefers-reduced-motion media query must wrap or override your scroll-driven animation declarations. Users who’ve opted into reduced motion in their OS settings have done so for a reason, often vestibular disorders or photosensitive conditions. Scroll-linked parallax effects are particularly disorienting for this group because the animation is continuous and tied directly to user input.
The correct pattern is either to remove the animation entirely under prefers-reduced-motion: reduce, or to substitute a fade (which is generally tolerable) for a large position-based movement. Do not just slow the animation down; that’s not what the user asked for.
There’s also a focus management concern if you’re using ViewTimeline to reveal content. If keyboard users tab into content that’s currently in a visually hidden state (opacity 0, or translated off-screen by an animation that hasn’t triggered yet), you have an invisible focus trap. This is fixable with visibility: hidden toggled alongside the opacity, but it requires deliberate thought rather than a copy-pasted animation snippet.
For anyone building design systems with motion at their core, the work I covered on building a design token pipeline with Style Dictionary applies here too. Motion tokens, durations, easing curves, and reduced-motion overrides can all live in your token system, making consistent and accessible animation much easier to maintain at scale.
Practical uses worth shipping right now
Given everything above, where does it make sense to actually use CSS scroll-driven animations today? Reading progress indicators are a no-brainer: they’re purely decorative, invisible absence is harmless, and the CSS is six lines. Sticky header opacity transitions work well. Subtle scale or fade effects on section headers as they enter the viewport add polish with minimal risk, provided the @supports and prefers-reduced-motion guards are in place.
Avoid: scroll-driven animations that carry meaning (i.e., the animation isn’t decorative but reveals content), complex parallax layers with multiple competing timelines, or anything that requires pixel-perfect timing across browsers, because the Safari gap makes that unreliable for now.
The spec is solid. The implementation is getting there. Ship it as an enhancement, test it properly, guard it correctly, and it genuinely improves the feel of a page without the JavaScript overhead we’ve been living with for years.

Leave a Reply