Scroll-Based Animations
With scroll-based animations, you can create animations that will trigger based on page scrolling rather than based on time.
The Scroll-driven Animations Specification defines two new types of timelines that you can use:
- Scroll Progress Timeline: a timeline linked to the scroll position of a scroll container along a particular axis.
- View Progress Timeline: a timeline linked to the relative position of an element within its scroll container.
How they work #
The easiest way to create a scroll animation is to use the scroll()
function to create an anonymous Scroll Timeline.
@keyframes animate-it {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.subject {
animation: animate-it linear;
animation-timeline: scroll(root block);
}
The scroll() function accepts two arguments: a scroller
and an axis
.
Valid values for the scroller
argument are:
- nearest (default)
- Uses the nearest ancestor scroll container (default).
- root
- Uses the document viewport as the scroll container.
- self
- Uses the element itself as the scroll container.
Valid values for the axis
argument are:
- block (default)
- Uses the measure of progress along the block axis of the scroll container
- inline
- Uses the measure of progress along the inline axis of the scroll container.
- y
- Uses the measure of progress along the y axis of the scroll container.
- x
- Uses the measure of progress along the x axis of the scroll container.
Creating a named Scroll Progress Timeline #
An alternative way to define a Scroll Progress Timeline is to use a named one.
To create a named Scroll Progress Timeline on an element follow these steps:
- Set the
scroll-timeline-name
CSS property on the scroll container to an identifier of your liking. The value must start with--
- To customize the axis to track declare the
scroll-timeline-axis
property- Allowed values are the same as the
axis
argument ofscroll()
3: To link the animation to the Scroll Progress Timeline, set theanimation-timeline
property on the element that you want to animate. This is the same value as thescroll-timeline-name
identifier.
- Allowed values are the same as the
We first create the @keyframes animation sequence.
@keyframes animate-it {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
We then set up the name of the scroller in its parent element (.scroller
) and then set up the scroller and animation in the element we want to animate (.scroller .subject
).
.scroller {
scroll-timeline-name: --my-scroller;
scroll-timeline-axis: inline;
}
.scroller .subject {
animation: animate-it linear;
animation-timeline: --my-scroller;
}
Using named scroll timelines enables us to use multiple animations on the same page since you can identify a Scroll Progress Timeline by the name that you assigned to it.
The Javascript option #
You can also create Scroll Timelines in Javascript.
To create a Scroll Timeline in JavaScript, create a new instance of the ScrollTimeline
class. Pass in a property bag with the source
and axis
that you want to track.
- source
- A reference to the element whose scroller you want to track. Use
document.documentElement
to target the root scroller. - axis
- Determines which axis to track. Similar to the CSS variant, accepted values are
block
,inline
,x
, andy
.
To attach it to a Web Animation, pass it in as the timeline
property to the animate
object and omit any duration if there was any.
const tl = new ScrollTimeline({
source: document.documentElement,
axis: block;
});
$el.animate({
opacity: [0, 1],
}, {
timeline: tl,
});
In Javascript, we can also target multiple scroll timelines.
Examples #
The most basic example is the progress bar at the top of the screen as the document scrolls down.
Using the HTML below, we'll look at CSS and Javascript solutions.
<div id="progress">
…
</div>
Both the CSS and Javascript versions will produce identical results.
CSS Scroll Progress Bar #
As discussed earlier, creating scroll timelines is a two-step process.
- We define the animation (or animations) that we want to use
- We assign the animation to our target element and we specify the animation timeline we want to use
/* 1 */
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
/* 2 */
animation: grow-progress auto linear;
animation-timeline: scroll();
}
The code produces these results:
Javascript Scroll Progress #
The Javascript version of the Scroll Progress indicator uses the Web Animations API for the animation.
The process is similar:
- Capture the target element
- Create the animation
- Attach the Scroll Timeline to the animation using the root (
document.documentElement
) scroller
// 1
const $progressbar = document.querySelector('#progress');
$progressbar.style.transformOrigin = '0% 50%';
// 2
$progressbar.animate(
{
transform: ['scaleX(0)', 'scaleX(1)'],
},
{
fill: 'forwards',
// 3
timeline: new ScrollTimeline({
source: document.documentElement,
}),
}
);
The code produces the following result:
Exploring scroll-based animations includes further exploring what you can and can't do with animations on the web, both CSS and WAAPI.