CSS animation-range Property
The animation-range property sets the start and end points of an animation's attachment within its timeline, specifically for scroll-driven animations.
| normal | Represents the default range of the timeline as defined by the animation-timeline. |
| <length-percentage> | Specifies a start or end offset from the beginning of the timeline using units or percentages. |
| entry | The range where the element is entering the scroll-port from the bottom or side. |
| exit | The range where the element is exiting the scroll-port at the top or opposite side. |
| cover | The full range of the element's visibility from the moment it enters until it completely leaves. |
| contain | The range where the element is fully contained within the scroll-port. |
| entry-crossing | The range while the element is crossing the starting edge of the scroll-port. |
| exit-crossing | The range while the element is crossing the ending edge of the scroll-port. |
Code Examples
A basic example showing an element that fades and scales in only during the 'entry' phase of its visibility in the scroll container.
<style>
.scroll-box {
height: 300px;
overflow-y: scroll;
}
.item {
height: 100px;
background: #333333;
margin: 400px 0;
animation: fade-in linear forwards;
view-timeline-name: --item-visible;
animation-timeline: --item-visible;
animation-range: entry 0% entry 100%;
}
@keyframes fade-in {
from { opacity: 0; transform: scale(0.5); }
to { opacity: 1; transform: scale(1); }
}
</style>
<div class="scroll-box">
<div class="item"></div>
</div>An advanced example using a global scroll timeline to fill a progress bar, with a specific percentage range and JavaScript support detection.
<style>
#progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 10px;
background: #ff0000;
transform-origin: 0% 50%;
animation: fill-up linear forwards;
animation-timeline: scroll();
/* Animation starts at 10% scroll and ends at 90% scroll */
animation-range: 10% 90%;
}
@keyframes fill-up {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
</style>
<div id="progress-bar"></div>
<div style="height: 2000px;">Scroll down to see the bar fill up between 10% and 90% of the page height.</div>
<script>
// Example of dynamically checking support and updating range
const bar = document.getElementById("progress-bar");
if (CSS.supports("animation-range", "10% 90%")) {
console.log("Scroll animations supported");
} else {
bar.style.display = "none";
}
</script>Pro Tip
You can combine named ranges with percentages for surgical precision. For example, "entry 20% exit 80%" tells the browser to start the animation 20% into the entry phase and finish it 80% through the exit phase. This creates a smooth buffer so the animation doesn't feel abrupt the moment the element touches the viewport edge.
Deep Dive
Think of animation-range like setting the "In" and "Out" points on a video editor's timeline. In traditional CSS, animations run based on time. With scroll-driven animations, the "timeline" is the scroll distance. This property allows you to define exactly when that animation sequence should kick in and when it should wrap up relative to an element's position in the viewport. It is a shorthand for animation-range-start and animation-range-end. By default, an animation mapped to a view-timeline will run the entire time the element is crossing the scrollport. By adjusting the range, you can make the animation finish early or start late, providing much tighter control over the user experience.
Best Practices
Stick to the animation-range shorthand to keep your stylesheets lean. Use named constants like "entry" and "exit" instead of hard-coded pixel values to ensure the effect works across different screen sizes. Since this feature is still relatively new and experimental in some browsers, always wrap your scroll-driven logic inside an @supports rule to provide a sensible fallback for users on older browsers.
Common Pitfalls
A common mistake is trying to use animation-range without first defining an animation-timeline; the property will do absolutely nothing without a timeline to reference. Also, remember that if you provide only one value, it sets both the start and end to that same point, which usually results in the animation not playing at all or jumping to the end instantly.
Accessibility
Scroll-linked animations can be disorienting or cause motion sickness for certain users. Always wrap your animation code in a media query for "prefers-reduced-motion: no-preference" to respect user system settings. Ensure that any information revealed via scroll-animation is also accessible if the animation fails to run.
Dev Data Table: animation-range property
| default | normal normal |
| animatable | no |
| inherited | no |
| experimental | yes |
| year_intro | 2023 |
| year_standard | 0 |
| js_syntax_1 | element.style.animationRange = "entry 10% exit 90%"; |
| js_syntax_2 | element.style.setProperty("animation-range", "cover 0% cover 100%"); |
| js_note | Ensure you check for browser support before manipulating scroll-timeline properties in JS to prevent script crashes in older environments. |
| browsers | { "Chrome": 115, "Edge": 115, "Firefox": 0, "Safari": 0, "Opera": 101, "Chrome Android": 115, "Safari on iOS": 0, "Samsung Internet": 23, "Opera Mobile": 77 } |