30
头图

In the CSS specification Scroll-linked Animations , an epoch-making CSS feature was introduced. That is -- The @scroll-timeline at-rule, which literally translates to scrolling timeline .

In this article, I will take you to find out, from getting started to learning to use CSS @scroll-timeline .

What is @scroll-timeline scrolling timeline?

What is @scroll-timeline rolling timeline?

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

Meaning, we can define an animation effect whose start and end can be controlled by scrolling the container .

Indicate DEMO

Before systematically learning grammar, let's take a brief look at its usage through a DEMO:

We first implement a simple font F rotation animation :

<div id="g-box">F</div>
#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);
    }
}

Normally, it's a simple animation like this:

Next, we combine this animation with @scroll-timeline , which needs to be placed into a scrollable container:

<div id="g-content">
    <div id="g-box">F</div>
</div>
#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");
}

Here, we implement a scrollable container #g-content whose height is 170vh , which is 1.7 times the height of the visual interface, and place the #g-box container at a height of 70vh from the top:

Interestingly, the rotation animation we set will not start automatically, only when we scroll down, the animation will start, the actual effect Gif:

CodePen Demo -- @scroll-timeline Demo

Seeing this, everyone should be able to understand the role and meaning of @scroll-timeline , It gives CSS the ability to control the animation based on the scrolling of the scroll bar! Amazing! !

Introduction to @scroll-timeline syntax

Next, let's take a moment and take a brief look at the syntax of @scroll-timeline .

Using @scroll-timeline , the most important thing is to define a @scroll-timeline rule:

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

in:

  • source: Bind the scroll container that triggers the scroll animation

    • source: auto : bind to Document , the global Windows object
    • source: selector("id-selector") , via selector() , with a built-in #id selector to select a scrollable container
    • source: none : scroll container not referring to
  • orientation: Set the direction of scrolling the timeline

    • orientation: auto : The default is vertical, which is vertical scrolling
    • orientation: vertical : vertical scrolling
    • orientation: horizontal : horizontal scrolling
    • orientation: block : less commonly used, uses scroll position along block axis, conforms to writing mode and directionality
    • orientation: inline : less common, uses scroll position along inline axis, conforms to writing mode and directionality
  • scroll-offsets: The core of scrolling the timeline, is set at what stage of scrolling to trigger the animation , which can be set in one of three ways:

    • scroll-offsets: none This means that no scroll-offset is specified.
    • Determined by a comma-separated list of <length-percentage> values. Each value maps to animation-duration . For example, if animation-duration is set to 2s and the scroll offset is 0px, 30px, 100px, at 1s the scroll offset will be 30px.
    • A third way to determine scroll offsets is to use element offsets. This means that elements within the page can be specified whose positions determine the scrolling timeline and which edge of those elements to use. Specifying an element is done using the selector() function, which receives the element's id. The edge is determined by the keyword start or end. An optional threshold of 0–1 can be used to represent the percentage of elements expected to be visible in scrolling.

scroll-offsets will be more difficult to understand, we will describe in detail later.

After setting a @scroll-timeline , we only need to bind it to the animation, through 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);
    }
}

Scrolling progress indicator using @scroll-timeline

Earlier in the Incredible Pure CSS Scrolling Progress Bar Effect , we introduced a pure CSS scrolling progress indicator effect implemented using gradients:

This method has some minor flaws. One of them is that when the scrolling distance is too short, the right side of the progress bar will have an obvious bevel effect.

And with @scroll-timeline , we can finally bind the two elements of scrolling and animation, and then implement the scrolling progress indicator, it is very easy:

<div id="g-container">
    <p>...文本内容...</p>
</div>
#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;
}
  1. At the top of the page, we use a pseudo element to implement a 5px high progress bar that fills the screen 100% . Normally this is:

  1. By setting an animation from transform: scaleX(0) to transform: scaleX(1) and binding it to the scrolling of the body, you can get the scroll indicator, the effect is as follows:

For the complete code, you can click here: CodePen Demo - Scrolling progress bar using @scroll-timeline

Use scroll-offsets to precisely control animation trigger timing

You can look at the Gif image above, there is a problem, that is, the start time of the animation starts from the beginning of the scroll, and ends just at the end of the scroll. So what if I want the animation to fire at a specific stage of scrolling?

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

During the scrolling process, we can divide an element into 3 areas:

  • During the rolling process, enter the field of vision from the blind spot of the upper field of view
  • During scrolling, in view
  • During the scrolling process, from the field of vision, enter the blind spot of the lower field of vision

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

For the upper and lower boundaries, there will be two states. The above boundary is an example, there will be:

  • The element has just started to enter the viewable area
  • The element fully enters the viewable area

For these two states, we use start 0 and start 1 represent, similarly, the lower boundary can also be represented by end 0 and end 1 :

The 0s and 1s here actually represent the percentage of expected to be visible in the scroll of elements.

With these state values, together with scroll-offsets , we can precisely control the trigger time of the scroll animation.

Let's set an animation from left to right and change with transparency. Let's take a look at the following situations:

  1. The scroll animation starts when the element begins to appear from below and ends when it appears completely.

Animation running range: 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;
}

The effect is as follows:

  1. The scroll animation starts when the element is fully visible from the bottom and ends when the element is scrolled to the top and is about to leave the screen:

Animation running range: 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;
}
// ...

The effect is as follows:

  1. The scroll animation starts when the element is scrolled to the top and is about to leave the screen, and ends when it completely leaves the screen:

Animation running range: 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;
}
// ...

The effect is as follows:

Mastering the usage of scroll-offsets is the key to flexible use of the scrolling timeline. Of course, you will also see the writing methods of start: selector(#g-box) start 1 and end: selector(#g-box) start 0 , which are left over from the history of the specification. The latest specification has used scroll-offsets to replace the writing methods of start: and end: . .

Put the above three cases together and compare them:

For the complete code, you can click here: CodePen Demo - @scroll-timeline Demo | element-based offset

Use @scroll-timeline to achieve various effects

After we can grasp the various syntaxes of @scroll-timeline, we can start to use it to create various animation effects.

For example, the scrolling content continues to enter:

The code is longer, you can click here, Codepen 162257541b0512 from CodePen Demo -- Fly-in Contact List (CSS @scroll-timeline version)

You can even combine scroll-snap-type make some full-screen scrolling large-screen special effects animations:

You know, this was completely impossible to achieve with pure CSS before. You can click here for the complete code: CodePen Demo -- CSS Scroll-Timeline Split Screen Carousel

In short, any animation effect can now be combined with scrolling, even with SVG elements. Here I simply modified a previous SVG line animation:

You can click here for the complete code: CodePen Demo -- SVG Text Line Effect | Scroll Timeline

Lab characterization and characterization testing for @scroll-timeline

Although @scroll-timeline is good, it is still in the laboratory feature time. Chrome supports it from version 85, but it is turned off by default.

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

In the latest chrome, Edge, and Opera, you can enable this feature through browser configuration. To enable this feature under Chrome, you need:

  1. Enter chrome://flags in the browser URL box
  2. Open #enable-experimental-web-platform-features

Although the wine is good, it will take a while for the browser to support large-scale support before it is fully usable. Give it some time!

Feature detection

Based on the current compatibility issues, we can use the feature of the browser to detect @supports syntax to progressively enhance the use of this function.

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;
    }
    // ...
}

Through @supports (animation-timeline: works) {} , you can judge whether the browser supports @scroll-timeline .

finally

There is very little introduction about @scroll-timeline, but it is a very big innovation that can change CSS animation. As compatibility grows in popularity, it's bound to have a place in CSS in the future.

This concludes this article, I hope it helps you :)

If you want to get the most interesting CSS information, don't miss my official account -- iCSS front-end anecdotes 😄

More wonderful CSS technical articles are summarized in my Github -- iCSS , which will be updated continuously. Welcome to click star to subscribe to the collection.

If you have any questions or suggestions, you can communicate more. Original articles are limited in writing and knowledge. If there are any inaccuracies in the article, please let me know.


chokcoco
12.3k 声望18.5k 粉丝