CSS scroll-timeline-axis Property
The scroll-timeline-axis property specifies the direction of scroll progress that should be used to drive an animation. It tells the browser whether to watch the vertical or horizontal movement of a scroll container to trigger keyframes.
| block | Uses the scrollbar on the block axis, which is the direction perpendicular to the flow of text in a line. |
| inline | Uses the scrollbar on the inline axis, which is the direction that text flows within a line. |
| y | Uses the vertical scrollbar, ignoring the writing mode or direction of the text. |
| x | Uses the horizontal scrollbar, ignoring the writing mode or direction of the text. |
Code Examples
A basic vertical scroll tracker that expands a progress bar at the top of the page as the user scrolls through a specific container.
<div id="container">
<div id="content">
Scroll down to see the progress.
</div>
</div>
<div id="progress-bar"></div>
<style>
#container {
height: 300px;
overflow-y: scroll;
scroll-timeline-name: --scroll-progress;
scroll-timeline-axis: block;
border: 2px solid #333333;
}
#content {
height: 1000px;
background: linear-gradient(#ffffff, #eeeeee);
}
#progress-bar {
height: 20px;
background: #00ff00;
width: 0%;
position: fixed;
top: 0;
animation: grow-progress auto linear forwards;
animation-timeline: --scroll-progress;
}
@keyframes grow-progress {
to { width: 100%; }
}
</style>An advanced horizontal gallery where items fade and scale as the user scrolls horizontally, including a JavaScript snippet to verify the axis.
<div id="gallery">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
<style>
#gallery {
display: flex;
overflow-x: auto;
width: 100%;
scroll-timeline-name: --gallery-scroll;
scroll-timeline-axis: inline;
padding: 20px;
gap: 20px;
}
.item {
min-width: 80%;
height: 200px;
background: #222222;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
animation: fade-in auto linear forwards;
animation-timeline: --gallery-scroll;
}
@keyframes fade-in {
from { opacity: 0.2; transform: scale(0.8); }
to { opacity: 1; transform: scale(1); }
}
</style>
<script>
// Log the scroll timeline axis via JS for debugging
const gallery = document.getElementById("gallery");
const currentAxis = getComputedStyle(gallery).scrollTimelineAxis;
console.log("Current animation axis is: " + currentAxis);
</script>Pro Tip
Instead of writing separate lines for name and axis, use the shorthand: scroll-timeline: --myTimeline block;. It makes your code cleaner and harder to break. You can also use the view() function for simpler scroll-driven animations if you only need to track an element as it enters the viewport, rather than tracking a specific scroll container.
Deep Dive
Think of this property as the directional setting for a progress bar. Standard animations move based on time, but scroll-driven animations move based on how far a user has scrolled. By setting the axis, you define which 'track' the animation follows. If you choose block, you are usually tracking vertical scrolling in standard Western layouts. If you choose inline, you are tracking horizontal movement. For this to work, the container must have overflow set to auto or scroll so that a scrollbar actually exists. Without a scrollbar, there is no progress to measure, and your animation will stay at its starting point. It is strictly used in conjunction with scroll-timeline-name to establish a complete Scroll Progress Timeline.
Best Practices
Stick to block for standard page-scrolling effects to ensure compatibility with different writing modes. Always ensure the container has enough content to actually trigger a scrollbar, otherwise the animation has no distance to travel. It is also wise to use the scroll-timeline shorthand property when you want to define both the name and the axis at the same time to keep your CSS organized.
Common Pitfalls
The most common mistake is trying to track an axis that doesn't have an overflow. If you set the axis to x but the container only scrolls vertically, the animation will not run. Developers also frequently confuse block and inline when working with vertical writing modes; remember that block follows the stack of text lines, not necessarily the vertical window axis.
Accessibility
Scroll-linked animations can cause motion sickness or disorientation for some users. You should always wrap your 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 aren't forced to view intense scroll-driven effects.
Dev Data Table: scroll-timeline-axis property
| default | block |
| animatable | no |
| inherited | no |
| experimental | yes |
| year_intro | 2022 |
| year_standard | 0 |
| js_syntax_1 | element.style.scrollTimelineAxis = "block"; |
| js_syntax_2 | element.style.setProperty("scroll-timeline-axis", "inline"); |
| js_note | When manipulating this in JavaScript, remember that the property is only effective if the element also has a defined scroll-timeline-name or is the designated source for a scroll-driven animation. |
| browsers | { "Chrome": 115, "Edge": 115, "Firefox": 0, "Safari": 0, "Opera": 101, "Chrome Android": 115, "Safari on iOS": 0, "Samsung Internet": 23, "Opera Mobile": 77 } |