Understanding timeline range names

By default, view progress timelines track elements across the entire scrollport. The animation timeline begins when the first pixel of the element's start edge crosses the scrollport's end edge, and ends when the element's end edge crosses the scrollport's start edge. You can change this default animation attachment range. For example, you can restrict the view progress timeline to begin only when the subject element has fully entered the scrollport.

This guide explains how to modify timeline range names, specifically examining the various timeline range names, their meanings, and how they are used.

View progress timeline primer

CSS animations are created by attaching @keyframes animations to an element using the animation-name property (or animation shorthand). The keyframes define the animation's behavior, while the animation-timeline determines when and how the element progresses through those keyframes.

By default, the animation's timeline is the document's default time-based DocumentTimeline. With CSS scroll-driven animations, the animation's timeline, or progress, is driven either by user scroll (scroll progress timelines) or element visibility (view progress timelines), instead of the passage of time.

With view progress timelines, keyframe progression is tied to how much of the subject element is visible within the scroller, and its position within the scroller. As the element enters the viewport, the timeline advances. If the user reverses the scrolling, the timeline reverses. In other words, as the element comes into or moves out of view, the timeline progresses or reverses, respectively. The animation only occurs when the subject is visible within its scrollport. If scrolling stops while the element is in view, the animation pauses.

Default view progress timeline

By default, the view progress timeline's progression starts when the tracked subject's start edge intersects the scrollport at the end edge and ends when the subject's end edge exits the scrollport at the start edge. These are the subject and scrollport's top and bottom edges when scrolling vertically, and the left and right or right and left edges when scrolling horizontally, depending on the writing mode.

In the following example, try scrolling down. Note how the animation begins just as the top edge of the animated element aligns with the bottom edge of the scroll container and ends, reaching 100% progress, when the bottom edge aligns with the top edge of the container, no matter how tall the animated element is.

The scroll container's writing mode and scroll direction determine the scroll container's start and end edges.

The animation attachment range

By default, the element is animated the entire time any portion of the subject element is visible. This means the default animation attachment range is the sum of the height of the scroll container and the height of the subject element, with that extra height being at the scroll end edge.

In the previous example, the scroll container is 250px tall, and the animated element is 50px tall by default, which means the vertical animation attachment range is 300px tall. When the subject is set to 250px, the range becomes 500px; when the element is set to 500px, the animation attachment range size grows to 750px.

The CSS scroll driven animations module provides mechanisms for defining different animation attachment ranges. The animation-range-start and animation-range-end properties, which can both be set using the animation-range shorthand, define the attachment range for the animation range's start edge and the end edge, along with any insets from either edge, respectively.

The animation-range properties accept the keyword normal, a <timeline-range-name>, a <length-percentage>, or both a <timeline-range-name> and the <length-percentage>. In this guide, we are covering the values for the <timeline-range-name> component of the value only.

Timeline range names

The <timeline-range-name> value type accepts six keywords: cover, contain, entry, exit, entry-crossing, and exit-crossing. Each of these represents a predefined named timeline range. A named timeline range is a named segment of an animation timeline. These keywords allow the developer to set the animation attachment range base that offsets are relative to. The start of the segment is represented as 0% progress through the range; the end of the segment is represented as 100% progress through the range. Where these points are depends on the named range used.

Cover

The animation attachment range in the previous examples all "cover" the entire range. This range represents the full range of the view progress timeline. 0% progress represents the point at which the start border edge of the subject aligns with the end edge of the scrollport, and 100% progress represents the point where the subject's end border edge reaches the start edge of the scrollport. As we've seen, the size of the cover range is the sum of subject and scrollport dimensions in the scroll direction. In all the examples thus far, the height of the animation attachment range is the height of the container plus the height of the animated element.

The cover named timeline range is the default range. We could have explicitly set the <timeline-range-name> to achieve the same results:

css
.animated_element {
  animation-range-start: cover;
  animation-range-end: cover;
}

The image demonstrates the animation timeline. The location of the element when it reaches the start of the animation attachment range's 0% mark is shown as a yellow block. This represents the element position when the from keyframe is applied. The red block represents the location of the subject element relative to the scrollport when the to keyframe is applied. This is the position of the animated element when it reaches the end of the animation.

Depending on the size of the subject element and the chosen timeline range, the start and end positions may overlap. Areas of overlap (as seen in subsequent diagrams) will be represented by striped red and yellow areas.

Contain

The contain named timeline range fully contains the animation within the scrollport — the range starts when the animated element is 100% visible and ends when it ceases to be fully visible, if it can be fully visible.

The contain value represents the range during which the principal box is either fully contained by or fully covers its view progress visibility range within the scrollport, depending on whether the subject element is smaller (can be fully contained by) or larger than the scrollport.

  • If the element is smaller than the scrollport in the scroll direction, 0% occurs when the animated element's end border edge aligns with the end edge of the scrollport, and 100% occurs when the animated element's start border edge aligns with the start edge of the scrollport. In other words, the contain value ranges from the point where the subject element is first completely contained by the scroll port (0%), to the point where it is no longer completely contained by the scroll port (100%).

  • If the element is larger than the scrollport, the 0% progress is when the animated element's start border edge reaches the start edge of the scrollport, and 100% is when the end border edge aligns with the end edge. In other words, if the animation is larger than its container, the animated element is never fully visible as it is not "contained" within the scrollport. The animation starts when the start edge reaches the start edge of the scrollport, and ends when the animated element's end edge reaches the end edge of the container.

  • If the animated element is the same size as its container, the animation still happens, but over 0px, which is not visible to the user.

css
.animated_element {
  animation-range: contain;
}

In this example, the original height of the animated element is 20% of the height of the scrollport, and therefore can be completely contained within it. As a result, as explained earlier, the animation should start as soon as the element starts to enter the scrollport, and finish as soon as it begins to leave the scrollport.

If you check the 500px radio button, the subject becomes twice as tall as the scrollport. The animation range begins when the subject element first completely covers the scroll port, with the 0% occurring when the start edge reaches the start edge of the container. It ends when the element no longer completely covers the scrollport, with the 100% occurring when the end edge crosses the container's end edge.

When the subject is the same size as the scroll container, as occurs when 250px is selected, the animation still occurs, but over 0px. As the 0% and 100% occur at the same time, the animation is instantaneous. The difference in styling is only perceivable because the properties defined in the 100% keyframe state are applied after the animation ends. This is because the animation-fill-mode property is set to forwards. Otherwise, the middle-sized 250px subject, being the same height as the scroll container, would appear not to animate at all.

The animation occurs when the element is within the areas represented by the white of the container in the 50px example and by the red/yellow areas in the 250px and 500px examples.

It may be helpful for some to compare and contrast the cover and contain values. We can use the shorthand animation-range property to set the animation-range-start and animation-range-end properties to the same <animation-name-range> value:

css
#A {
  animation-range: contain;
}
#B {
  animation-range: cover;
}

Select different radio buttons and scroll the scrollport to compare the effects of the cover and contain values on animation timelines.

Let's look at the other <timeline-range-name> keyword values!

Entry and exit

To make the entire animation happen only when the subject is in the process of entering or exiting the scrollport, use the entry or exit values, respectively. With these two values, the animation attachment range is based on the size of the animated element, not the size of the scrollport.

Entry

With entry, 0% progress occurs the moment the animated element starts to enter the scrollport, when the subject's start edge crosses the scrollport's end edge.

The entire animation occurs as the subject comes into view, ending when it becomes completely visible or when it reaches the start edge; whichever occurs first. If the animated element is smaller than the scrollport, the animation attachment range is the size of the subject.

The position at 0% progress is shown in yellow. The position at 100% progress is displayed in red. When the animated element is larger than the scrollport, these two positions overlap, which is denoted by a striped background.

With entry, the animation attachment range is either the size of the animated element or the size of the container, whichever is smaller. If the subject is larger than the scrollport, the animation attachment range is the entire scrollport. With entry, the 100% occurs when the subject's end edge crosses the end edge of the scrollport or, if the animated element is larger than the scrollport in the scroll direction, when the animated element's start edge reaches the start edge of the scrollport.

Setting animation-range-start: entry is the same as setting animation-range-start: cover. Setting animation-range-end: entry is equivalent to setting animation-range-end: contain.

Exit

The exit value is the inverse of entry. With exit, the attachment range starts when the animated element's start edge crosses the scrollport's start edge.

The 0% progress occurs when the subject's start edge reaches the scrollport's start edge. The 100% progress occurs when the subject's end edge crosses the start edge. Setting animation-range-start: exit 0% is equivalent to setting animation-range-start: contain 100%. Setting animation-range-end: exit 100% is equivalent to animation-range-end: cover 100%.

Comparing entry and exit

It may help to take a look at entry and exit side-by-side to understand the effect the size of the subject has on the animation attachment range: with these two values, the animation attachment range is never larger than the container.

css
#A {
  animation-range: entry;
}
#B {
  animation-range: exit;
}

Scroll the viewbox to see the range of the entry and exit values, then change the size of the subjects using the radio buttons and scroll again.

When the subjects are small enough to be fully contained within the scrollport, the animation attachment timeline is at the start (entry) or end (exit) of the scrollport and the size of the attachment range is limited to the size of the animated element in the scroll direction.

With entry and exit, the animation range is contained to the size of the scrollport, while the element is not.

If the subject element is the size of the scrollport or larger:

  • In the case of entry, the animation ends when the element fully covers the scrollport in the scroll direction.
  • In the case of exit, the animation doesn't begin until, the element fully covers the scrollport in the scroll direction.

This may not be the effect you want. If you want an entry animation to keep running until the entire element has finished entering the start edge of the scrollport, or if you want an exit animation to start as soon as the element starts to exit the end edge of the scrollport, you need to use entry-crossing and exit-crossing.

Entry- and exit-crossing

If the subject element is smaller than the scrollport, and you want the full animation to occur as it enters or exits the scrollport, you can happily use entry or exit, respectively.

When the subject is larger than the scrollport, the animation doesn't run the full course of the element entering or exiting the scrollport. The entry value sets the 100% progress to be when the element's start edge reaches the start-edge of the scrollport, before the element has fully entered the scrollport. With exit, the 0% progress occurs when the element's end-edge reaches the scroll container's end edge, when part of the subject has already exited the scrollport. With both these values, the animation attachment range is smaller than the subject. If this isn't the effect you want, the *-crossing values may be the solution you seek.

Entry-crossing

The entry-crossing value represents the range during which the animated element crosses the end edge of the scrollport, with 0% progress occurring when the element's start edge aligns with the end edge the scrollport and 100% progress occurring when the element's end edge reaches the end edge of the scrollport, meaning it has finished fully scrolling into the scrollport.

It may be helpful to compare the two values in a live example.

css
#A {
  animation-range: entry;
}
#B {
  animation-range: entry-crossing;
}

Select the the different height values, then scroll to compare entry with entry-crossing for each size.

Note how the effects are similar, except for when the 500px is selected and the animated element is taller than the container. The entry-crossing range produces the same results as entry when the element is equal to or smaller than the scrollport, but when the element is larger than the scrollport, the 100% occurs later, occurring only when the end edge has entered the view port. The animation attachment range is the size of the subject, and not clamped to the size of the scrollport.

Exit-crossing

The exit-crossing value represents the range during which the animated element crosses the start edge of the scrollport, with 0% progress occurring when the element's start edge aligns with the start edge the scrollport and 100% progress occurring when the element's end edge reaches the start edge of the scrollport.

With exit-crossing, the animation starts as soon as the subject covers the scrollport (with exit, the animation doesn't start until the end edge of the subject enters into view). In both cases, the animation continues until the subject fully exits the scrollport's start edge.

css
#A {
  animation-range: exit;
}
#B {
  animation-range: exit-crossing;
}

The exit-crossing produces the same results as exit when the element is equal to or smaller than the scrollport, but when the element is larger than the scrollport, the 0% occurs earlier, occurring as soon as the element's start edge reaches the scrollport's start edge, rather than waiting until the element's end edge enters the scrollport.

Like with entry-crossing, the animation attachment range is the size of the subject, and not clamped to the size of the scrollport.

See also