Modern CSS scroll-driven animations
Scroll-driven animations are a new CSS feature that lets animations progress based on scroll position instead of time. This creates performant, native parallax effects, progress indicators, and reveal animations without JavaScript.
Unlike JavaScript scroll listeners, CSS scroll-driven animations run on the compositor thread, providing buttery-smooth 60fps performance. The browser optimizes these animations automatically.
Currently supported in Chrome/Edge 115+, with Firefox and Safari implementing. Use
@supports for progressive enhancement and provide JavaScript fallbacks for older
browsers.
This section scales in and out as it enters and exits the viewport using
animation-timeline: view().
.progress-bar {
position: fixed;
top: 0;
height: 4px;
background: linear-gradient(...);
transform-origin: left;
}
@supports (animation-timeline: scroll()) {
.progress-bar {
animation: progressGrow linear;
animation-timeline: scroll();
}
@keyframes progressGrow {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
}
@supports (animation-timeline: scroll()) {
.hero-bg {
animation: heroParallax linear;
animation-timeline: scroll();
}
@keyframes heroParallax {
to { transform: translateY(50vh); }
}
}
@supports (animation-timeline: view()) {
.content-card {
animation: fadeInView linear;
animation-timeline: view();
animation-range: entry 0% cover 30%;
}
@keyframes fadeInView {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
}
if (!CSS.supports('animation-timeline: scroll()')) {
const progress = document.getElementById('progressBar');
window.addEventListener('scroll', () => {
const scrolled = window.scrollY;
const total = document.body.scrollHeight - window.innerHeight;
const percent = scrolled / total;
progress.style.transform = `scaleX(${percent})`;
}, { passive: true });
}