Understanding timeline insets
By default, view progress timelines track elements across the entire animation attachment range, and the 0% progress point is at the start and 100% progress point is at the end of that range, respectively. The animation attachment range can be changed setting a timeline range name, and the location of the 0% and 100% progress points can be inset along the range by setting length or percentage-based insets.
The various timeline range names, their meanings, and how they are used are discussed in the timeline range name guide. This guide explains limiting the animation timeline to a specific portion of the animation timeline range, effectively insetting the animation timeline, using length or percentage values.
Animation timelines: a primer
CSS animations are created by defining named @keyframes animations, which define an animation's behavior, and then attaching the keyframe animation to an element using the animation's name.
The element's animation timeline, defined by the animation-timeline property, determines how and when the element progresses through those keyframes. By default, the timeline is time-based, using the document's default time-based DocumentTimeline.
The CSS scroll-driven animation module defines scroll-based and view-based timelines, which are methods of animating property values along a scroll-based timeline rather than the default time-based document timeline.
View progress timelines
With view progress timelines, the animation's timeline, or progress, is driven by element visibility instead of the passage of time, with keyframe progression tied to the subject element position and visibility within the scroll container. The animation advances and reverses as the element advances or reverses through the scrollport. The animation only occurs when at least part of the element is visible within its scrollport, pausing when scrolling pauses.
.animated_element {
animation-name: nameOfAnimation;
animation-timeline: view();
}
Setting an animation-name applies the animation to the selected element. The animation-iteration-count defaults to 1. The animation-direction defaults to normal. See the Using CSS animations guide to learn more.
Note:
The animation-timeline property should always come after any animation shorthand declarations. While the shorthand property can not be used to set the animation-timeline property, it does reset the timeline to the default time-based document timeline.
In every example, the scroll container is 250px tall. As you scroll up, the animation progresses. As you scroll down, the animation reverses.
In this example, note how any time any part of the subject element is visible in the scrollport, the animation is occurring. By default, view progress animations begin just as the top edge of the subject element aligns with the bottom edge of the scroll container and end, reaching 100% progress, when the end edge aligns with the start edge of the container, no matter the size of the subject element. By default, the animation is applied when any part of the the subject is visible within the scrollport.
Animation attachment ranges
When no animation range properties are defined, the animation is applied the entire time any portion of the subject element is visible, meaning 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.
By default, the 0% progression in a view timeline progress occurs when the subject element's start edge intersects the scrollport at the end edge, reaching 100% progress when the subject's end edge exits via the scrollport's 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 our example, as the scroll container is 250px tall, and the subject is either 50px, 250px, or 500px tall, the vertical animation attachment range is 300px, 500px, or 750px, depending on which radio button is selected.
Whether the range is 300px, 500px, or 750px tall, the animation's 0% progress mark is when the top edge of the subject aligns with the bottom of the scrollport and the 100% progress is when the bottom edge of the subject aligns with the scrollport's top edge.
We can visualize the position of the subject at the 0% and 100% progress points for the three subject sizes:
The yellow subject elements represents the position of the element when the from keyframe is applied, which is the animation range's 0% progress mark. The red represents the location of the animated element relative to the scrollport when the to keyframe is applied, which is the end of the animation, or the 100% progress mark. The grey represents the scrollport.
By default, the element animates while it is "in view", but this default definition of "in view" may not fit your needs. Fortunately, animation range properties enable us to control which edges define the ends of the edges of the animation attachment range and then the start and end of that range by a <length> or a <percentage> relative to named or default timeline range.
Animation range properties
The animation-range properties enable setting a named timeline range and then insetting animations from the animation attachment ranges using <length-percentage> inset values, such as 20% or 100px.
The animation-range-start and animation-range-end properties, which can both be set using the animation-range shorthand, define an animation's attachment range, limiting the keyframe's active interval to that specific portion of the range.
These properties specify the start and end of the animations's attachment range, shifting the start time and/or end of the animation, where the 0% and 100% keyframes occur when the animation-iteration-count is set or defaults to 1. Both the start and end offsets are from the start of the attachment range.
Setting an inset is similar to setting the animation-delay on time-based DocumentTimeline animations. Just like the animation-delay property can delay the animation start until 500ms after the animation is otherwise applied, the animation-range-start property can be used to delay a view progress timeline animation until 50px of the subject are in view. The animation-range-end property can similarly end the animation early. We also have the animation-range shorthand property, which can both move the from animation progress point to a scroll position occurring after the default 0% progress point and move the to animation progress point to a scroll position occurring before the default 100% progress point.
See the timeline range name guide to learn about the predefined named timeline ranges. The focus of this guide is insetting the starts and ends of the animation attachment range using <length-percentage> inset values, regardless of which animation timeline range is set.
Setting insets using lengths
The animation-range-start and animation-range-end properties each accept a named animation range, a <length-percentage> offset value, or both. Any length or percentage offset is from the start of the animation attachment range.
When a <length> is set, the offset is fairly intuitive.
Here we use the animation-range-start and animation-range-end properties to inset the animation timeline. In this way, we define a subsection of the element's full animation attachment range as the active interval, set the distance from the start of the animation attachment range.
.animated_element {
animation-range-start: 1em;
animation-range-end: 125px;
}
This defines the start and end of the animation as being 1em and 125px from the start of the animation attachment range, respectively. In this case, the start of the animation attachment range is the block end edge of the container.
We've added a lines 1em and 125px from the block end edge of the scroll container. The animation starts when the block start edge of the subject element reaches the line 1em line and ends when it reaches the 125px line.
In this case, as the animation attachment range is the same for both properties, the location of the insets was fairly straightforward.
Lengths and ranges
The offset distance is always from the start of the associated animation range. If you set the following, the animation will start 50px from the start of the normal range and end 100px from the start of the entry range:
.animated_element {
animation-range-start: 50px;
animation-range-end: entry 100px;
}
As the start edge of both the normal and entry ranges is the container's end edge, the animation begins when the subject start edge is 50px from the bottom of the scrollport and ends, reaching 100% progress, when the subject start edge is 50px from the bottom of the scrollport, irrespective of the subject size. While the size of the entry range is different for the three different subject size, in this case the size of the underlying range didn't matter.
Length offsets with varying ranges
The size of range matters when the range doesn't start at the element's end edge, as is the case with exit and exit-crossing, or if the offset is a percentage value. This fact, and the fact that you can mix and match animation range names, make understanding timeline range names important while making view progress timeline offsets a bit more complicated.
For example, when setting exit as the timeline range name, the subject size matters as it determines where the location of the end edge of the range.
.animated_element {
animation-range-start: entry 50px;
animation-range-end: exit 75px;
}
The offset position is relative to the start of the declarations animation range. With animation-range-start set to entry 50px, the animation's 0% progress occurs 50px from the container's end edge (denoted by the blue line) for all three subject sizes; this is the same as in the previous example.
The animation-range-end is where things get interesting. We've set the end of the range to be 75px from the start edge of the exit range. The exit attachment range is the opposite of entry. With exit, the range being the size of the subject, up to the size of the scrollport, with the 0% progress occurring when the animated element's start edge crosses the scrollport's start edge and the 100% progress occurring when the subject's end edge crosses the scrollport's start edge.
Beyond the scrollport edges
Offsets that are larger than the subject create animations-range-start or animation-range-end points that occur when no part of the subject is visible.
When the subject is 50px tall, the exit range is 50px. The point 75px from the start of the exit range past the start edge of the scrollport. The animation only ends when the subject's start edge is 75px past the scrollport's start edge and the end edge is 25px past.
With our 250px tall container, when the subject is 250px or 500px tall, the exit range is the size of the container, with the start being the scroll container's end edge. With a 75px offset, the end of the animation occurs when the end edge of the subject is 75px from the end edge of the scroll container (denoted with a red line).
The animation ends, meaning animation continues to the to keyframe and the animationend event occurs, even if the animation range end is outside of the scrollport, as long as there is room to scroll to that point. Had we set animation-range-end: exit 250px, the animation would have ended when the end edge of the medium and tall subjects exited the scrollport at the container's start edge. The small subject's animation may not end as there may not be 450px worth of content after the subject in our example for the user to scroll until the animation end is reached.
Negative lengths
Negative lengths are valid. A negative offset on the animation-range-start makes the range longer while a negative offset on the animation-range-end makes the range shorter.
Let's compare the negative insets compared to the 0 values:
#A {
animation-range-start: contain -25px;
animation-range-end: exit -25px;
}
#B {
animation-range-start: contain 0;
animation-range-end: exit 0;
}
The first animation range is offset by 25px toward the container end edge.
Setting insets using percentages
Like length values, percentage values define offsets from the start of the animation attachment range. The percentage offsets are relative to the timeline range dimension, not relative to the scrollport. For this reason, percentage values are not as intuitive as length values for most people.
Here use animation-range-start and animation-range-end to inset the animation timeline. While we are using the same properties, we set <percentage> values instead of <length> values:
.animated_element {
animation-range-start: 20%;
animation-range-end: 60%;
}
This defines the active interval to begin 20% into the default attachment range and end 60% through that same range. The default normal animation attachment range, which behaves as cover, is the height of the scroll container plus the height of the subject element, meaning the range will differ based on which radio button is selected.
For illustrative purposes, there are grey lines crossing the container at the 20% and 60% points of the scrollport's height, measured from from the bottom of the scrollport. As the animation-range-* percentages are relative to the timeline range, not the scrollport, these lines only show how the percentages don't align. Based on the height of our subjects, the 20% mark is either 60px, 100px, or 150px from the end edge of the scrollport (marked with a red line), and the 60% mark is 180px, 300px, or 450px from the same point (marked with a green line).
The animation starts when the block-start edge reaches the green 20% line and ends when the start block edge meets the 60% line. Only when the element is 50px tall is the top of the subject still in the scrollport when the end of the animation is reached; there are no red lines when 250px or 500px are selected.
We've added grey horizontal lines 20% and 60% from the bottom of the container to demonstrate their lack of reference; reinforcing that the animation attachment range on which the offsets are based is not the container.
The following image demonstrates where the subject elements are located when the animation starts (the 0% keyframe) and ends (the 100% keyframe).
This image includes the insets from the animation timeline in the previous demonstration and the timeline without insets for comparison.
As before, the yellow represents the position of the element when the from keyframe is applied, the red represents the location when the to keyframe is applied, and the grey represents the scrollport. The striped areas are where the red and yellow element representations overlap. For illustrative purposes, we've added dashed black horizontal lines 20% and 60% way through the scrollport, starting from the bottom.
The animation only begins when the element reaches the 20% mark along the animation attachment range. This point is that is 60px, 100px, or 150px from the bottom edge of the scroll port, depending on the the size of the element, is the animation's 0% progress point. The location of the subject element at this point, representing the position of the element when the from or 0% keyframe is applied, is shown in yellow.
The red represents the location of the animated element relative to the scrollport when the to or 100% keyframe is applied, which is the end of the animation. This point is either 180px, 300px, or 450px from the bottom edge of the scrollport, depending on the subject size. The animation occurs when the element is between the to and the from positions; between the positions along the animation attachment range defined.
You may have noticed something interesting about the dashed horizontal lines: when the animation starts, the line that is 20% from the end edge of the viewport is 20% from the top of the subject element and the line that is 60% from the end edge of the viewport is 60% from the top of the subject element when the animation ends.
Subject size matters
As we've seen, the size of the subject can make a difference. For some named ranges, the size of the attachment range is based on the subject size.
The percentage values are relative to the size of animation attachment range, not the scrollport. Percentages are based on the size of the range, impacting the insets. Depending on the name, the start position may also change, impacting the location of the range and therefore the location of progress points.
.animated_element {
animation-range-start: exit-crossing -20%;
animation-range-end: exit-crossing 20%;
}
The animation lasts 40% of the animation-attachment range. As you scroll, note how the larger the subject, the longer the range.
Percentages equal to the scrollport
For the start and end percentages to be relative to the scrollport and the subjects, we use the <timeline-range-name> keyword contain along with the percentage for each of our animation-range-* values.
The contain range fully contains the animation within the scrollport. It represents the range during which the principal box is either fully contained by, or fully covers, its view progress visibility range within the scrollport. With contain, if the subject is the same size or smaller than the scrollport, it can be fully visible, but if the element is the same size as the container, the animation is over 0px, so happens, but is not visible to the user.
.animated_element {
animation-range-start: contain 25%;
animation-range-end: contain 75%;
}
Without needing to know the size of the container or the subjects, we are able to limit our animation to the middle of scrollport.