CSS animation-range-start Property
This property sets the start point of an animation's range along a scroll-driven timeline.
| normal | The default value where the animation starts at the very beginning of the timeline. |
| <length-percentage> | A specific distance or percentage along the timeline where the animation begins its playback. |
| cover | The animation starts when the element first starts to enter the scrollport. |
| contain | The animation starts when the element is fully contained within the scrollport. |
| entry | The animation starts as the element begins its entrance into the scroll container. |
| exit | The animation starts as the element begins to leave the scroll container. |
| entry-crossing | The animation starts when the element crosses the start edge of the scrollport. |
| exit-crossing | The animation starts when the element crosses the end edge of the scrollport. |
Code Examples
A basic example showing an element that begins fading in only after it is 50% through its entry into the viewport.
<style>
.scroll-box {
height: 300px;
overflow-y: scroll;
border: 1px solid #000000;
}
.item {
height: 100px;
background-color: #008000;
animation: fade-in linear forwards;
animation-timeline: view();
animation-range-start: entry 50%;
animation-range-end: contain 100%;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
</style>
<div class="scroll-box">
<div style="height: 500px;">Scroll down to see the green box fade in.</div>
<div class="item"></div>
<div style="height: 500px;"></div>
</div>An advanced example using a scroll timeline where the start range is dynamically updated using JavaScript.
<style>
#progress-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 10px;
background-color: #ff0000;
transform-origin: 0 50%;
animation: scale-progress linear forwards;
animation-timeline: scroll();
animation-range-start: 10%;
}
@keyframes scale-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
</style>
<div id="progress-bar"></div>
<div style="height: 2000px; padding: 20px;">
<h1>Advanced Scroll Progress</h1>
<p>The red bar at the top will only start growing after you have scrolled 10% down the page.</p>
<button onclick="adjustStart()">Change Start to 50%</button>
</div>
<script>
function adjustStart() {
const bar = document.getElementById("progress-bar");
bar.style.animationRangeStart = "50%";
bar.style.backgroundColor = "#0000ff";
console.log("Range start updated to 50%");
}
</script>Pro Tip
You can combine a keyword and a percentage, such as "entry 25%". This acts like a fine-tuning knob, allowing you to say, "Start this animation when the element is a quarter of the way through its entry phase," giving you pixel-perfect control over reveals.
Deep Dive
Think of a scroll-driven animation like a movie track that plays as you move the scrollbar. By default, the movie starts at the very first frame when the scroll starts. This property lets you place a marker further down that track. If you set it to 20%, the animation stays at its first frame until you have scrolled 20% of the way through the defined timeline. It works by mapping specific scroll positions or element visibility thresholds to the 0% progress point of your CSS keyframes. This is a game changer for creating parallax effects or reveal animations that only trigger when an element is actually visible on the screen.
Best Practices
Always use named ranges like "entry" or "exit" when you want an animation to be relative to an element's position in the viewport. It makes your code much easier to read and maintain than using abstract percentages. Pair this property with animation-range-end to create a specific window where the animation is active, preventing it from running longer than necessary.
Common Pitfalls
The most common mistake is trying to use this property with standard time-based animations (like those using seconds or milliseconds). It only functions when an animation-timeline is explicitly set to a scroll or view timeline. Also, if your start range is set further than your end range, the animation simply won't run.
Accessibility
Scroll-driven animations can be disorienting for users with motion sensitivities. Always wrap your scroll-driven animation logic inside a media query that checks for prefers-reduced-motion: no-preference. This ensures that users who have requested less movement on their screen don't get hit with unexpected shifting elements.
Dev Data Table: animation-range-start property
| default | normal |
| animatable | no |
| inherited | no |
| experimental | no |
| year_intro | 2023 |
| year_standard | 2023 |
| js_syntax_1 | element.style.animationRangeStart = "entry 20%"; |
| js_syntax_2 | element.style.setProperty("animation-range-start", "cover 10%"); |
| js_note | When manipulating this in JavaScript, ensure the browser supports scroll-driven animations or use a polyfill to avoid runtime errors. |
| browsers | { "Chrome": 115, "Edge": 115, "Firefox": 0, "Safari": 0, "Opera": 101, "Chrome Android": 115, "Safari on iOS": 0, "Samsung Internet": 23, "Opera Mobile": 77 } |