Scroll Spy Indicator
A reading progress bar that tracks scroll position using CSS scroll-driven animations.
Published May 19, 2026
Demo
The Future of CSS
CSS has evolved dramatically over the past decade. What began as a simple styling language now supports animations, logical properties, and even scroll-driven effects.
Scroll-driven animations are one of the most exciting additions to the platform. They let you tie animation progress directly to a scroll position — entirely without JavaScript.
How It Works
The animation-timeline property accepts a scroll() function that references a scroll container. The browser maps the scroll range to the animation's progress.
A simple @keyframes that goes from width: 0% to width: 100% becomes a reading progress bar with a single CSS property.
Browser Support
Scroll-driven animations are supported in all modern evergreen browsers. No polyfill, no fallback JavaScript needed for the vast majority of users.
HTML
<div class="reading-bar"></div>
<article><!-- page content --></article>
CSS
.reading-bar {
position: sticky;
top: 0;
width: 100%;
height: 5px;
background: #e0e0ea;
}
.reading-bar::after {
content: "";
display: block;
height: 100%;
background: linear-gradient(90deg, #5b4cdb, #e040fb);
animation: reading-progress linear;
animation-timeline: scroll(root block);
}
@keyframes reading-progress {
from { width: 0%; }
to { width: 100%; }
}
How it works
animation-timeline:scroll() links an animation's progress to a scroll container. scroll(root block) tracks the page scroll; scroll(nearest block) tracks the nearest scrollable ancestor. The @keyframes simply go from width:0 to width:100%. The browser drives the animation position based on scroll — no requestAnimationFrame needed.