Can you do scroll animations in CSS without JavaScript?
Yes. animation-timeline lets scroll position drive a keyframe animation directly, so the effects that animate-on-scroll libraries provide need no JavaScript at all in browsers that support it.
Free, local and no login
Animate elements as the reader scrolls to them, using the browser’s own scroll timelines. No IntersectionObserver, no scroll listener, no animation library — the motion is CSS, and the browser advances it from scroll position.
Create an animationA working example with the exact code it produces. Copy it, or open it in the editor and change anything.
.body-copy {
transform: translate3d(70px, 143px, 0);
width: 340px;
height: 34px;
background: #00000000;
color: #8b90a0;
font-size: 18px;
font-weight: 400;
animation: body-copy-anim 1200ms linear 0ms infinite both;
will-change: transform, opacity;
}
@keyframes body-copy-anim {
0% {
transform: translate3d(70px, 161px, 0);
opacity: 0;
animation-timing-function: ease-out;
}
50% {
transform: translate3d(70px, 143px, 0);
opacity: 1;
}
100% {
transform: translate3d(70px, 143px, 0);
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.body-copy {
animation: none;
transition: none;
}
}Keep the distance small — 16 to 24px. Long travel makes a page feel slow to read because the eye follows the movement instead of the words. This is the entrance to reach for when you are not sure which to use.
Reveal sections as they enter the viewport
Tie a progress bar or parallax to page scroll
Replace an animate-on-scroll library with native CSS
Build the animation on the timeline as usual.
Set the layer’s timeline to “Scroll into view” and pick the range.
Export — the timeline ships behind @supports, with a load-time fallback.
Yes. animation-timeline lets scroll position drive a keyframe animation directly, so the effects that animate-on-scroll libraries provide need no JavaScript at all in browsers that support it.
It maps an animation to the element’s own journey through the viewport, so the animation progresses as the element scrolls into and across the screen. animation-range then chooses which slice of that journey the animation covers.
MotionCraft emits the scroll timeline inside an @supports block and leaves a normal time-based animation in the plain rule. Browsers without support play the animation on load instead, so nothing is left invisible — which is the failure mode to avoid with a scroll-driven fade.
Yes. The generated prefers-reduced-motion guard silences scroll-driven animations along with the rest.