CSS Scroll-Timeline and View-Timeline Explained
CSS scroll-driven animations revolutionize web interactions by
decoupling keyframe animations from traditional time-based durations and
tying them directly to scroll progress. Through the
scroll-timeline and view-timeline
specifications, developers can create complex, fluid scroll effects
natively within CSS, removing the need for resource-intensive JavaScript
scroll event listeners and significantly boosting rendering
performance.
Understanding Scroll-Driven Animations
Traditionally, CSS animations run along a temporal timeline defined in seconds or milliseconds. The CSS Scroll-Driven Animations specification introduces progress-based timelines where 0% represents the start of a scroll container or element intersection, and 100% represents the end. Because these animations run natively in the browser's compositor thread, they do not block the main thread, effectively eliminating scroll jank and layout thrashing.
The
scroll-timeline Specification
The scroll-timeline links animation progress to the
overall scroll position of a scroll container (the scrollport). As the
user scrolls through the container from top to bottom (or left to
right), the animation advances linearly from 0% to 100%.
Key properties include:
scroll-timeline-name: Declares a custom identifier (e.g.,--page-scroll) on the scroll container.scroll-timeline-axis: Specifies the scroll direction to monitor (block,inline,y, orx). The default isblock.animation-timeline: Applied to the animated element, referencing the timeline name defined on the container.
Alternatively, developers can use the shorthand function
scroll() directly on the animation-timeline
property to target the nearest ancestor scroller or the root viewport
without explicitly naming the container.
Primary Use Cases:
- Reading progress bars indicating article completion.
- Sticky navigation bars that shrink or change background color as the user leaves the top of the page.
- Parallax background layers moving at variable rates relative to page scroll.
The view-timeline
Specification
While scroll-timeline tracks the entire scroll
container, view-timeline tracks an individual subject
element's visibility as it enters, traverses, and leaves the visible
scroll area (the scrollport).
Key features include:
view-timeline-name: Applied directly to the subject element being observed (e.g.,--revealing-image).view-timeline-axis: Specifies the scroll orientation, typically defaulting toblock.animation-range: Controls precisely when the animation starts and ends relative to the element's intersection with the scrollport. Ranges includeentry(entering the view),exit(leaving the view), andcover(from entering to completely exiting).
Like scroll(), the shorthand function
view() can be declared directly within
animation-timeline on the animated element.
Primary Use Cases:
- Revealing cards, images, or headings with fade-in and scale effects as they enter the screen.
- Staggered list animations that trigger only when elements reach the viewport.
- Exit animations that blur or rotate elements as they scroll out of view.
Practical Implementation
To create a global reading progress bar using
scroll():
@keyframes stretch {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 4px;
transform-origin: left;
animation: stretch linear;
animation-timeline: scroll(root block);
}To reveal an image as it scrolls into view using
view():
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(40px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card {
animation: fade-in linear both;
animation-timeline: view();
animation-range: entry 20% cover 40%;
}By leveraging scroll-timeline for container-level
tracking and view-timeline for element-level intersection
tracking, web developers can achieve precise, declarative, and
high-performance interactive animations without relying on third-party
JavaScript libraries.