Scroll-Based Animations in Full View()

The CSS `animation-timeline` property accepts a `view()` function which returns a timeline of how much of an element is visible in a scroll container’s viewable area, known as a scrollport. Instead of running an animation based on elapsed time, `view()` bases animations on an element’s visibility within a scrollport.

I liken it to the CSS equivalent of JavaScript’s Intersection Observer. We can animate an element as it enters and exits the scrollport.

Here’s an example:

Pretty neat, right? Depending on an image’s position in the scrollable carousel, it transitions from small and blurry at the edges to larger and clearer at the center. There’s also some scroll snapping to ensure each image makes a stop.

It’s not difficult to achieve! I’ll show you how it’s essentially the same animation you’re used to writing in CSS, but applied on a view timeline instead of a normal one.

But first, the general layout

I’m creating an element called `.carousel`:



The elements in `.carousel` will layout in a single row using flexbox. We’ll ensure any overflowing content is scrollable:

“`css
.carousel {
display: flex;
width: max(480px, 50vw);
overflow-x: auto;
}
“`

We need scrollable items, like image slides:

Each item will be one-third the size of the available space, showing three items at a time:

“`css
.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’ve set `overflow-x` on the `.carousel`, making it our scroll container. We can add scroll snapping to scroll one item at a time.

“`css
.carousel {
/* same as before */

scroll-snap-type: x mandatory;
scroll-behavior: smooth; /* optional for smooth scrolling */
scrollbar-width: none; /* optional to hide the scrollbar */
}
“`

Ensure slides align to the center when snapping:

“`css
.carousel-slide {
/* etc. */
scroll-snap-align: center;
}
“`

Here’s what we have so far:

Next, the animation

A view timeline animation is the same as any CSS animation with keyframes. We want keyframes where carousel items are small and blurry at the start and end, becoming larger and clearer in the middle.

“`css
@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;
}
}
“`

This CSS is familiar! Set the animation on the element as usual:

“`css
.carousel-slide {
/* etc. */
animation: slide;
}
“`

The difference is the animation runs on a timeline based on the element’s `view()` instead of the regular timeline, using `animation-timeline`:

“`css
.carousel-slide {
/* etc. */
animation: slide;
animation-timeline: view(inline);
}
“`

Technically, the timeline could be included in the `animation` shorthand, but it’s not supported by browsers yet. Declare it separately after the `animation` shorthand to avoid overriding with `auto`.

That completes our demo:

See that? We’ve set a CSS animation that runs on elements. Instead of the default timeline, the animation runs when an element scrolls in and out of view. That’s the distinction between standard and view timelines.

`view()` vs. `scroll()`

`view()` timelines are part of CSS Scroll-Driven Animations. `view()` isn’t the only function supported by `animation-timeline`. There’s also the `scroll()` function.

The `scroll()` function creates a scroll progress timeline tied to

Similar Posts