Reading progress indicators, header shrinking effects, and scroll-linked image zooms are staple features of high-engagement editorial web design. Historically, delivering these experiences demanded binding JavaScript scroll listeners, which continuously queried window.scrollY and recalculated styles on the browser main thread. This script execution frequently resulted in dropped frames during rapid trackpad scrolling. The CSS Scroll-Driven Animations specification introduces the native scroll-timeline property, allowing animation progress to be driven directly by container scroll offsets on the compositor thread. This tutorial covers configuring scroll-timeline and auditing animation timing in Google Chrome.
The Mechanics of CSS Scroll Timelines
A scroll timeline tracks the progress of a scroll container from its start scroll position (0%) to its maximum scroll boundary (100%). Authors declare an anonymous scroll timeline via animation-timeline: scroll() or assign a named timeline using scroll-timeline-name: --reading-progress; scroll-timeline-axis: block; on the scroll container. Downstream elements link to this driver via animation-timeline: --reading-progress;. Because keyframe interpolation is computed on the GPU compositor, animations execute at a continuous 120 FPS without JavaScript overhead.
Authoring a Zero-JavaScript Reading Progress Bar
Configure an editorial progress bar pinned to the top of the browser window:
/* 1. Define keyframe transform */
@keyframes scaleProgress {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
/* 2. Attach scroll timeline directly to document scrollbar */
.reading-progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
transform-origin: 0% 50%;
z-index: 1000;
/* Native declarative scroll timeline */
animation: scaleProgress auto linear;
animation-timeline: scroll(root block);
}
Configuring Scoped Scroll Timelines on Sub-Containers
When scroll-driven animations exist inside nested overflow containers (such as an embedded code block or scrollable side panel):
.sidebar-scroll-pane {
overflow-y: auto;
scroll-timeline-name: --panel-scroll;
scroll-timeline-axis: block;
}
.panel-header-shadow {
animation: fadeShadow linear both;
animation-timeline: --panel-scroll;
animation-range: 0px 50px;
}
@keyframes fadeShadow {
from { box-shadow: none; }
to { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); }
}
Auditing Scroll Timelines in Chrome DevTools
- Launch Google Chrome and navigate to your editorial page.
- Press
F12orCtrl + Shift + Ito launch Chrome DevTools. - Open the Animations tab (
Ctrl + Shift + P>Show Animations). - Scroll the article up and down. Chrome DevTools captures the scroll timeline session, displaying the scrubbed progression alongside CSS animation keyframe values.
- In the Rendering panel, ensure Scrolling performance issues displays zero warnings, confirming that the animation is running entirely on the compositor thread.
Providing Graceful Feature Detection
Ensure backwards compatibility for legacy browsers using an @supports feature query:
.reading-progress-bar {
display: none;
}
@supports (animation-timeline: scroll()) {
.reading-progress-bar {
display: block;
}
}
This progressive enhancement pattern hides the bar on legacy browsers without breaking document presentation, while providing responsive, hardware-accelerated scroll tracking on modern Chrome clients.