The CSS animation-timeline property accepts one view() function that in turn returns a timeline of how much of an element is visible in the part of a scroll container that is visible (formally known as a scroll gate). In other words, instead of making an animation perform a linear progression based on elapsed time, view() performs animations based on the visibility of the animated element within a scrollport.
I like to compare it to the CSS version of JavaScript’s Intersection Observer. We can perform an animation on an element as that element enters and exits the scrollport.
Here’s an example:
Pretty neat, right? Depending Where an image is in the scrollable carousel, it becomes small and blurry on the other sides and becomes larger and clearer when it lands in the center. We also have a little scroll click there to make sure each image item stops.
It’s not that hard to do! I’ll show you how it’s basically the same old animation you’re used to writing in CSS, just applied to a display timeline instead of a normal timeline.
But first the general layout
All I’m creating here is an element that I’m evoking .carousel:
The elements in it .carousel is drawn up in one row, that is a one-liner with flexbox. We also ensure that all content that exceeds space is scrollable:
.carousel {
display: flex;
width: max(480px, 50vw);
overflow-x: auto;
}And of course we need items in it that we can scroll through. A series of image slides.
As for the styling of these items, each item will be a third of the available space, so that when scrolling we see three items at once:
.carousel {
/* same as before */
.carousel-slide {
flex-shrink: 0;
width: calc(100% / 3); /* show three at a time */
aspect-ratio: .8;
img {
width: 100%;
}
}
}Then the scrolling
We’re already set overflow-x on the .carouselmaking it officially our scroll container. We can add a little scroll snapping to make sure we only scroll one item at a time.
.carousel {
/* same as before */
scroll-snap-type: x mandatory;
scroll-behavior: smooth; /* optional for smooth scrolling */
scrollbar-width: none; /* optional to hide the scrollbar */
}We want to make sure the slides are aligned with the center of the scroll container when they snap into place:
.carousel-slide {
/* etc. */
scroll-snap-align: center;
}This is what we have so far:
Then the animation
Here’s the really cool thing I mentioned at the beginning: a rendering timeline animation is basically the same as any other CSS animation you write with keyframes. In this case, we want keyframes where the carousel items are small and blurry at the beginning and end, but become larger and clearer in the middle of the animation.
@keyframes slide {
/* from start to 45%, and to the end (100%) */
45%, 100% {
transform: scale(0.5);
border-radius: 20px;
filter: blur(6px) brightness(.8);
}
/* middle */
50% {
transform: scale(1);
border-radius: 4px;
filter: none;
}
}Looks familiar, right? This is the kind of CSS you’ve been writing forever! And guess what? We place the animation on the element we are animating, just as you normally would:
.carousel-slide {
/* etc. */
animation: slide;
}The only difference is that we want the animation to run on a timeline based on the current value of the element view() instead of the regular timeline. That’s where the animation-timeline ownership plays a role:
.carousel-slide {
/* etc. */
animation: slide;
animation-timeline: view(inline);
}Now, technical speaking, we could place that timeline directly in the text animation shorthand property like any other constituent animation property, for example animation-name, animation-delay, animation-durationetc. But assigning a timeline function this way is not yet supported by any browser. So for the time being it is best to indicate it yourself. Just make sure you declare it after the animation shorthand, otherwise you may find yourself accidentally overwriting your view timeline auto (the default property value) instead of view().
That completes our demo:
Do you see that? All we really did is set up a CSS animation that runs on elements. However, instead of running on the default timeline, the animation runs as an element scrolls in and out of view. That’s the difference between standard and display timelines.
view() vs scroll()
But wait! You may or may not know that view() timelines are part of a larger feature set called CSS Scroll-Driven Animations. And view() is not the only feature supported by the animation-timeline property. We also have the scroll() function.
The scroll() function creates a scroll progress timeline that is linked to the scroll position of a container, while view() creates a view the progress timeline which is based on the visibility of an element in its container.
Both features are useful in their own way! I think in general view() is better for item-specific disclosure effects. So for example if we want to animate a slide only if that specific slide slides into the scrollportthen the view() function fits perfectly. That’s why I focused on this for our carousel example: we want to track the position of an element in the scrollport and animate it accordingly.
Betting parameter and animation-range
You might also be wondering what on earth is in parentheses view() function. After all, it’s a feature, so there has to be something in it, right?
CSS view() has two arguments: ash (block, inline, xAnd y) and the stake. The inset parameter defines an offset from the edges of the scrollport within which the animated element is tracked. The official syntax looks like this:
animation-timeline: view( ); …which is just a fancy way to get specific about exactly which parts of the scrollport we want to activate the animation. With some animations, starting and ending the timeline when the element fully enters and exits the scrollport can cut things off.

That’s not good! We want each item to slide fully in when it comes fully into the scroll port, and not when it goes fully out. That’s why all the items look so spread out: they’re all at different points in the display timeline.
That’s where the betting parameter makes a big difference. We can be more specific by saying that we want each element to start an animation when it appears at the bottom of the scrollport.
animation: slide-in linear both;
animation-timeline: view(100% 0%);Oh, much better:
The animation-range real estate works along similar lines.
animation-range: entry; /* same as: entry 0 entry 100%; */The animation-range property accepts a whole host of other keywords, including exit (when the element leaves the scrollport), cover (when the element starts coming in, it starts leaving the scrollport), and contain (when the element fully enters and then fully exits the scrollport), among other things. Geoff has published a number of notes and examples looking specifically at each.
One final carousel example
In general, carousels use effects such as fading in and out, scaling and parallax. However, because most CSS properties are animable, and even those that are not can be tricked into doing so by using registered CSS properties (as in the case of gradient lines), you have the opportunity to explore more creative ways to use them view() for carousels.
Here’s an example where an animation of just the background position creates a nice movement in a carousel.
#Create #scrollbased #animations #full #view #CSS #tricks


