CSS animation-range-start and animation-range-end Guide
This article provides a concise overview of how the CSS
animation-range-start and animation-range-end
properties define the precise boundaries of scroll-driven animations.
You will learn the mechanics behind these properties, the syntax and
values they accept—including percentages, lengths, and named
view-timeline ranges—and how they determine exactly when an animation
starts and finishes along a scroll timeline.
Understanding Scroll Timeline Boundaries
In modern CSS scroll-driven animations, an animation's progress is mapped to scroll progress rather than elapsed wall-clock time. By default, an animation runs from the very beginning of the scroll container to the very end.
The animation-range-start and
animation-range-end properties allow developers to override
this default behavior. They define the specific scroll positions where
the animation timeline begins (0% progress) and completes (100%
progress), effectively segmenting the scroll area into active and
inactive zones.
Syntax and Accepted Values
Both properties accept values that determine an offset along the scroll or view timeline. These values fall into three primary categories:
1. Percentages and Lengths
When using standard scroll timelines (such as scroll()),
positions are typically declared using percentages or length values:
- Percentages: Relative to the total scrollable
overflow.
animation-range-start: 20%begins the animation when the user has scrolled 20% down the container. - Lengths: Fixed distances such as
px,vh, orrem.animation-range-end: 500pxends the animation when the scroll offset reaches 500 pixels.
2. Named Timeline Ranges
When using a view timeline (view()), the progress
depends on the visibility of a subject element inside the scrollport.
CSS provides predefined range names to target specific phases of element
visibility:
cover: Spans from the moment the subject first enters the scrollport until it fully exits.contain: Spans from the moment the subject is fully visible inside the scrollport until any part of it starts to leave.entry: Spans from the moment the subject enters the scrollport until it is fully inside.exit: Spans from the moment the subject begins to leave the scrollport until it has completely left.entry-crossing: Spans from the moment the subject begins entering the scrollport until it crosses the opposite edge.exit-crossing: Spans from the moment the subject begins exiting until it fully crosses the starting edge.
3. Named Ranges with Percentage Offsets
Named ranges can be combined with a percentage to fine-tune the boundaries:
.card {
animation-range-start: entry 0%;
animation-range-end: entry 100%;
}In this example, the animation starts the instant the card enters the view and finishes as soon as it is fully visible, remaining static for the remainder of the scroll.
Default Values
The default value for both properties is normal.
- On a standard
scroll()timeline,normalresolves to0%foranimation-range-startand100%foranimation-range-end. - On a
view()timeline,normalresolves tocover 0%for the start andcover 100%for the end.
The animation-range
Shorthand
You can combine both properties into the animation-range
shorthand property:
/* Syntax: animation-range: <start> <end>; */
.element {
animation-range: entry 20% exit 80%;
}If only one value is provided to the shorthand:
- If the value is a named range without a percentage (e.g.,
animation-range: entry), it expands to cover the entire named range:entry 0% entry 100%. - If the value is a length or percentage (e.g.,
animation-range: 20%), it sets the start boundary to that value while the end boundary defaults tonormal.
Example Implementation
The following example demonstrates a fade-in effect that begins as soon as the target element begins entering the screen and completes once it has entered by 50%:
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(40px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animated-box {
view-timeline-name: --boxTimeline;
view-timeline-axis: block;
animation-name: fadeIn;
animation-timeline: --boxTimeline;
animation-fill-mode: both;
/* Configure the boundaries */
animation-range-start: entry 0%;
animation-range-end: entry 50%;
}By constraining the boundaries with
animation-range-start and animation-range-end,
the animation reaches its final state early in the scroll cycle and
remains fixed in place as the user continues scrolling.