π What Is animation-timeline?
The animation-timeline property connects a CSS animation to acustom timeline β such as a scroll timeline created with@scroll-timeline. Instead of progressing over time, animations can progress based on scroll position,view timeline, or other future timeline types. πβ¨
π§© Basic Syntax
Basic Syntax
animation-timeline: none | auto | <timeline-name>;- none β no timeline (normal time-based animation)
- auto β browser decides the timeline
- <timeline-name> β use a custom timeline you defined
π― animation-timeline with @scroll-timeline
Use @scroll-timeline to create a scroll-driven Timeline, TimelineItem, then use animation-timeline to bind your animation to it.
1οΈβ£ Define Scroll Timeline
@scroll-timeline
@scroll-timeline fadeTimeline {
source: auto;
orientation: block;
scroll-offsets: 0%, 100%;
}2οΈβ£ Define Keyframes
@keyframes
@keyframes fadeIn {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}3οΈβ£ Attach Timeline to Animation
animation-timeline usage
.section {
animation-name: fadeIn;
animation-duration: 1s; /* no longer time-based */
animation-timeline: fadeTimeline;
animation-range: 0% 100%; /* Progress based on scroll */
}β Now the animation progresses smoothly as the user scrolls.
β No JavaScript required.
π¬ animation-timeline with View Timelines
Instead of scrolling the whole page, you can animate based on when an elemententers or exits the viewport.
1οΈβ£ Create a View Timeline
View Timeline
.card {
view-timeline-name: cardTimeline;
view-timeline-axis: block;
}2οΈβ£ Attach animation-timeline
Attach view timeline
.card {
animation-name: fadeIn;
animation-timeline: cardTimeline;
animation-range: entry 0% exit 100%;
}β Card fades in as it enters the viewport
β Finishes as it leaves
π¦ Real Examples
1οΈβ£ Progress Bar Based on Scroll
Scroll progress bar
@scroll-timeline progressTimeline {
source: auto;
}
.progress {
animation: fillBar 1s linear;
animation-timeline: progressTimeline;
animation-range: 0% 100%;
}
@keyframes fillBar {
from { width: 0%; }
to { width: 100%; }
}2οΈβ£ Parallax Background
Parallax
@scroll-timeline parallaxScroll {
scroll-offsets: 0%, 100%;
}
.bg {
animation: parallaxShift 1s linear;
animation-timeline: parallaxScroll;
}
@keyframes parallaxShift {
from { transform: translateY(0); }
to { transform: translateY(-200px); }
}3οΈβ£ Reveal Animation on Section Entry
Reveal on entry
.section {
view-timeline-name: revealTimeline;
view-timeline-axis: block;
animation: reveal 1s ease-out;
animation-timeline: revealTimeline;
animation-range: entry 0% exit 100%;
}
@keyframes reveal {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}π Understanding animation-range (Works with animation-timeline)
animation-range
animation-range: entry 0% exit 100%;β Controls where animation starts and ends within the scroll or view timeline
- entry β element starts entering viewport
- exit β element leaves viewport
- Use percentages to define animation progress
π§ Browser Support
- β Chrome 115+
- β Edge 115+
- β Firefox (not supported yet)
- β Safari (partially behind flags)
Note
π οΈ Best Practices
- Use scroll-driven animations for performance (avoid JS scroll listeners)
- Animate transforms for smooth GPU-accelerated motion
- Keep animations subtle β avoid overwhelming the user
- Use view timelines for "enter reveal" effects
- Test behavior with varying scroll lengths and device sizes