Real CSS, not JS
The preview is driven entirely by animation-timeline and animation-range — genuine scroll-linked CSS animation.
Scroll the demo panel to preview real scroll-driven CSS animations, tune the range, and copy working animation-timeline code.
This box animates purely with CSS as you scroll. No JavaScript scroll listeners are involved.
Build entrance animations that are perfectly in sync with how far someone has scrolled, without a single scroll event listener.
The preview is driven entirely by animation-timeline and animation-range — genuine scroll-linked CSS animation.
Compare a scroll-container-based timeline against a view-based timeline that reacts to the element itself entering the viewport.
Grab the full @keyframes block plus the animation-timeline and animation-range declarations.
Traditionally, CSS animations run on a fixed time-based clock: you set a duration and the animation plays from 0% to 100% regardless of what the user is doing on the page. Scroll-driven animations replace that clock with a scroll-based progress source using the animation-timeline property. A scroll() timeline maps 0% to 100% of the animation onto the scroll progress of a scrollable ancestor, so the animation plays forward as you scroll down and reverses as you scroll up. A view() timeline instead tracks how far the animated element itself has traveled through the nearest scrollport, which is usually the better choice for "reveal on scroll" effects because it triggers relative to the element's own position rather than the container's total scroll distance. The animation-range property narrows or shifts exactly which portion of that timeline the animation plays across, so you can make an element finish animating well before it reaches the center of the viewport, for example.
The browser drives the animation directly on the compositor, which is typically smoother than a scroll event handler.
A narrow range like 0% to 40% finishes the animation quickly; a wide range stretches it across more scroll distance.
Wrap scroll-driven animations in an @media (prefers-reduced-motion: no-preference) query out of respect for motion-sensitive users.
animation-timeline is a CSS property that lets an animation's progress be driven by something other than time, such as the scroll position of a container (scroll()) or how far an element has scrolled into view (view()), instead of a fixed duration.
scroll() maps the animation to the scroll progress of a scrollable ancestor from 0% to 100% of its scroll range. view() maps the animation to how far the animated element itself has traveled through the visible scrollport, which is usually better for triggering an animation as an element enters and leaves the viewport.
animation-range sets the start and end points of the timeline, as percentages, over which the animation plays. Narrowing the range makes the animation play faster over a shorter scroll distance instead of stretching across the whole timeline.
Scroll-driven animations have broad support in Chromium-based browsers such as Chrome and Edge. Support is still expanding in other engines, so for production use it is worth checking current browser support and providing a fallback.
A common fallback is to detect support with CSS.supports('animation-timeline: scroll()') and, if it returns false, use an IntersectionObserver in JavaScript to add or remove a class that triggers a regular time-based CSS transition or animation instead.
Keep building with these free online CSS tools.