Skip to main content
Dublin Library

The Publishing Project

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).
Uses the document viewport as the scroll container.
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
Uses the measure of progress along the inline axis of the scroll container.
Uses the measure of progress along the y axis of the scroll container.
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:

  1. Set the scroll-timeline-name CSS property on the scroll container to an identifier of your liking. The value must start with --
  2. To customize the axis to track declare the scroll-timeline-axis property
    1. Allowed values are the same as the axis argument of scroll() 3: To link the animation to the Scroll Progress Timeline, set the animation-timeline property on the element that you want to animate. This is the same value as the scroll-timeline-name identifier.

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.

A reference to the element whose scroller you want to track. Use document.documentElement to target the root scroller.
Determines which axis to track. Similar to the CSS variant, accepted values are block, inline, x, and y.

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;

  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.

  1. We define the animation (or animations) that we want to use
  2. 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:

  1. Capture the target element
  2. Create the animation
  3. Attach the Scroll Timeline to the animation using the root (document.documentElement) scroller
// 1
const $progressbar = document.querySelector('#progress');

$ = '0% 50%';

// 2
    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.

Edit on Github