An epoch-making CSS feature has been introduced in the CSS specification Scroll-Linked Animations. The @scrolltimeline at-rule.

This article will take you from getting started to learning how to use CSS @scrolltimeline.

What is @scrolltimeline?

What is @scrolltimeline?

@scroll-timeline allows you to set the start and end of an animation to be determined by the scrolling progress within the scroll container, rather than by time.

This means that we can define an animation effect whose start and end can be controlled by scrolling the container.

A sign for the DEMO

Before we look at the syntax in a systematic way, let’s use a simple DEMO to see how it can be used:

Let’s start by implementing a simple rotation animation of the font F:

<div id="g-box">F</div>
Copy the code
#g-box {
    animation-name: rotate;
    animation-duration: 3s;
    animation-direction: alternate;
    animation-easing-function: linear;
}
@keyframes rotate {
    0% {
        transform: rotate(0);
    }
    100% {
        transform: rotate(360deg); }}Copy the code

Normally, it is a simple animation like this:

Next, we combine this animation with @scroll-timeline and need to place it in a scrollable container:

<div id="g-content">
    <div id="g-box">F</div>
</div>
Copy the code
#g-content {
    width: 300px;
    height: 170vh;
    background: # 999;
}
#g-box {
    font-size: 150px;
    margin: 70vh auto 0;
    animation-name: rotate;
    animation-duration: 3s;
    animation-direction: alternate;
    animation-easing-function: linear;
    animation-timeline: box-rotate;
}
@keyframes rotate {
    0% {
        transform: rotate(0);
    }
    100% {
        transform: rotate(360deg); }}@scroll-timeline box-rotate {
    source: selector("#g-content");
}
Copy the code

Here we implement a scrollable container # G-content that is 170vh tall, or 1.7 times the height of the visual interface, and place the # G-Box at a height of 70vh from the top:

The interesting thing is that the rotation animation we set will not start automatically, it will only start when we scroll down. Gif:

CodePen Demo — @scroll-timeline Demo

The @scroll-timeline gives CSS the ability to control animation based on the scrolling of the scroll bar. Backpacks!!!!!

@scrolltimeline Syntax description

Let’s pause for a moment and take a quick look at the @scrolltimeline syntax.

To use @scroll-timeline, the core is to define a @scroll-timeline rule:

@scroll-timeline moveTimeline {
  source: selector("#g-content");
  orientation: vertical;
  scroll-offsets: 0px.500px;
}
Copy the code

Among them:

  • Source: Binds the scroll container that triggers the scroll animation
    • source: auto: to bind toDocumentThat is, the global Windows object
    • source: selector("id-selector")Through theselector(), built-in one#idSelector to select a scrollable container
    • source: none: does not refer to the rolling container
  • Orientation: Set the orientation of the scrolling timeline
    • orientation: autoThe default value is vertical, that is, scroll in the vertical direction
    • orientation: vertical: Vertical roll
    • orientation: horizontal: Horizontal scrolling
    • orientation: block: Less commonly used, using a scrolling position along the block axis, conforming to writing patterns and directionality
    • orientation: inline: Not very common, uses the scroll position along the inline axis, conforms to the writing pattern and direction
  • 2. The core of the scroll-offsets,At what stage of the scroll should the animation be triggered, can be set in one of three ways:
    • scroll-offsets: noneThat means there is no scrolloffset specified.
    • The value is a list of length-percentage values separated by commas. Each value is mapped to animation-duration. For example, if ananimation-duration is set to 2s and the scroll offset is 0px, 30px, 100px, then at 1s the scroll offset will be 30px.
    • The third way to determine the roll offset is to use the element offset. This means that you can specify elements within the page whose position determines the scrolling timeline and which edge of those elements to use. Specify that the element is done using the selector() function, which accepts the element’s ID. The edge is determined by the keyword start or end. An optional threshold of 0-1 can be used to indicate the expected percentage of visibility in element scrolling.

Scroll offsets are difficult to understand, and we’ll go into more detail later.

After setting an @scroll timeline, we just need to bind it to the animation, using animation-timeline:

@scroll-timeline moveTimeline {
  source: selector("#g-content");
  orientation: vertical;
  scroll-offsets: 0px.500px;
}
div {
    animation-name: move;
    animation-duration: 3s;
    animation-timeline: moveTimeline;
}
@keyframes move{
    0% {
        transform: translate(0.0);
    }
    100% {
        transform: translate(100%.0); }}Copy the code

Use @scroll-timeline to implement the scroll progress indicator

Earlier in the incredible Pure CSS scroll progress bar effect, we introduced a pure CSS scroll progress indicator effect using gradient:

There are some minor flaws in this approach. One is the noticeable hypotenuse effect on the right side of the progress bar when scrolling too short.

With @scroll-timeline, we can finally bind the two elements of scroll and animation, and implement the scroll progress indicator, which is very easy:

<div id="g-container">
    <p>. Text content...</p>
</div>
Copy the code
#g-container {
    width: 100vw;
}
#g-container::before {
    content: "";
    position: fixed;
    height: 5px;
    left: 0;
    top: 0;
    right: 0;
    background: #ffc107;
    animation-name: scale;
    animation-duration: 1s;
    animation-fill-mode: forwards;
    animation-timeline: box-rotate;
    transform-origin: 0 50%;
}

@keyframes scale {
    0% {
        transform: scaleX(0);
    }
    100% {
        transform: scaleX(1); }}@scroll-timeline box-rotate {
    source: auto;
    orientation: vertical;
}
Copy the code
  1. We implement a full screen with a fake element at the top of the page100%5pxHigh progress bar. Normally this is the case:

  1. By setting up atransform: scaleX(0)transform: scaleX(1)And bind it to the body scroll to get the scroll indicator, which looks like this:

For the complete code, you can poke here: CodePen Demo – Implement the scrolling progress bar using @scroll-timeline

Use scroll-offsets to accurately control animation trigger timing

If you look at the Gif above, the problem is that the animation starts at the beginning of the scroll and ends right at the end of the scroll. So what if I want the animation to fire during a particular phase of the scroll?

Here, we need to use scroll offsets to control our animation more accurately.

During scrolling, we can divide an element into three regions:

  • During the rolling process, from the upper view blind area, into the view
  • In view of the rolling process
  • During scrolling, from the field of view, into the blind area of the lower field of view

Here, we can get two boundaries, the upper boundary and the lower boundary:

And for the upper and lower boundaries, there are two states. As an example, the above boundary would have:

  • The element is just beginning to enter the viewable area
  • The element is fully visible

For these two states, we use start 0 and start 1. Similarly, we can use end 0 and end 1 to represent the lower boundary:

The zeros and ones here actually represent the percentage of elements that are expected to be visible in scrolling.

With these state values, and with the scrolloffsets, we can precisely control the trigger time of the scroll animation.

Let’s create an animation that moves from left to right with a change in transparency, and look at the following situations:

  1. The scrolling animation begins when the element appears from below and ends when it is fully present.

End 0 –> end 1:

@keyframes move {
    0% {
        transform: translate(-100%.0);
        opacity: 0;
    }
    100% {
        transform: translate(0.0);
        opacity: 1; }}@scroll-timeline box-move {
    source: auto;
    orientation: "vertical";
    scroll-offsets: 
        selector(#g-box) end 0.selector(#g-box) end 1;

    /* Legacy Descriptors Below: */
    start: selector(#g-box) end 0;
    end: selector(#g-box) end 1;
    time-range: 1s;
}
#g-box {
    animation-name: move;
    animation-duration: 3s;
    animation-fill-mode: both;
    animation-timeline: box-move;
}
Copy the code

The effect is as follows:

  1. The scrolling animation starts when the element is fully visible from below and ends when it is about to leave the screen after scrolling to the top:

End 1 –> start 1:

// ...
@scroll-timeline box-move {
    source: auto;
    orientation: "vertical";
    scroll-offsets: 
        selector(#g-box) end 1.selector(#g-box) start 1;

    /* Legacy Descriptors Below: */
    start: selector(#g-box) end 1;
    end: selector(#g-box) start 1;
    time-range: 1s;
}
// ...
Copy the code

The effect is as follows:

  1. The scroll animation starts when the element has rolled up and is about to leave the screen, and ends when the element has completely left the screen:

Start 1 –> start 0:

// ...
@scroll-timeline box-move {
    source: auto;
    orientation: "vertical";
    scroll-offsets: 
        selector(#g-box) start 1.selector(#g-box) start 0;

    /* Legacy Descriptors Below: */
    start: selector(#g-box) start 1;
    end: selector(#g-box) start 0;
    time-range: 1s;
}
// ...
Copy the code

The effect is as follows:

Start: selector(#g-box) start: selector(#g-box) end: selector(#g-box) Selector (#g-box) start 0. This is a legacy of the spec. The latest spec uses scroll offsets instead of start: and end:.

Put these three situations together and compare:

The complete code, you can stamp here: CodePen Demo – @ scroll – timeline Demo | element – -based offset

Use @scrolltimeline to achieve various effects

Once you’ve mastered the syntax of @Scrolltimeline, you can start using it to create animation effects.

For example, the scrolling content is continuously delimited:

Codepen Codepen Demo — fly-in Contact List (CSS @scroll timeline version)

You can even combine scrollsnap-type to make some large screen special effects animations with full screen scrolling:

Remember, this was completely impossible with pure CSS in the past. CodePen Demo — CSS Scrolltimeline Split Screen Carousel

In short, any animation effect can now be combined with scrolling, even with SVG elements. Here’S a simple adaptation of an earlier SVG line animation:

The complete code you can stamp here: CodePen Demo – SVG Text Line Effect | Scroll Timeline

@scrolltimeline Laboratory features and feature detection

@scrollTimeline, while good, is still a lab feature. Chrome has been supporting it since version 85, but it’s off by default.

Compatibility is as follows (2022-03-07):

To enable this feature in Chrome, Edge, and Opera, you need to:

  1. Enter the browser URL boxchrome://flags
  2. open#enable-experimental-web-platform-features

The wine is good, but it will be a while before it is fully functional and the browser supports it on a large scale. Give it time.

Feature detection

Based on current compatibility issues, we can incresively enhance the use of this feature by checking the @supports syntax in the browser features.

The syntax for feature detection is also very simple:

@supports (animation-timeline: works) {
    @scroll-timeline list-item-1 {
	source: selector(#list-view);
	start: selector(#list-item-1) end 0;
	end: selector(#list-item-1) end 1;
        scroll-offsets:
            selector(#list-item-1) end 0.selector(#list-item-1) end 1
        ;
	time-range: 1s;
    }
    // ...
}
Copy the code

@supports (animation-timeline: works) {} to determine whether the browser supports @scrolltimeline.

The last

@scrolltimeline hasn’t been much talked about yet, but it’s a big innovation that could change CSS animation. With the increasing popularity of compatibility, CSS will definitely have a place in the future.

That’s the end of this article, I hope it was helpful 🙂

Want to Get the most interesting CSS information, do not miss my public account – iCSS front-end interesting news 😄

More interesting CSS technology articles are summarized in my Github — iCSS, constantly updated, welcome to click on the star subscription favorites.

If there are any questions or suggestions, you can exchange more original articles, writing is limited, talent and learning is shallow, if there is something wrong in the article, hope to inform.