Wednesday, December 10, 2025

Creating Scroll-Based mostly Animations in Full view()


The CSS animation-timeline property accepts a view() perform which, in flip, returns a timeline of how a lot of a component is seen within the a part of a scroll container that’s viewable (formally often called a scrollport). In different phrases, fairly than letting an animation run a linear development based mostly on how a lot time has elapsed, view() runs animations based mostly on the visibility of the animated factor inside a scrollport.

I prefer to equate it because the CSS model of JavaScript’s Intersection Observer. We are able to run an animation on a component as that factor enters and exits the scrollport.

Right here’s an instance:

Fairly neat, proper? Relying on the place a picture is within the scrollable carousel, it goes from small and blurry on the far sides whereas getting bigger and clearer when it hits the middle. We’ve got slightly scroll snapping in there as nicely to ensure every picture merchandise makes a cease.

It’s not that onerous to do! I’ll present you the way it’s actually the identical outdated animation you’re used to writing in CSS, solely utilized on a view timeline as a substitute of a standard timeline.

However first, the final structure

All I’m making right here is a component I’m calling .carousel:

The weather in .carousel will lay out in a single row, which is a one-liner with flexbox. We’ll additionally make it possible for any content material overflowing its area is scrollable:

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

And, in fact, we’d like objects in it that we will scroll round. A set of picture slides.

So far as styling these objects, every one will probably be one-third the dimensions of the obtainable area in order that we see three objects at a time when scrolling:

.carousel {
  /* similar as earlier than */

  .carousel-slide {
    flex-shrink: 0;
    width: calc(100% / 3); /* present three at a time */
    aspect-ratio: .8;
    img {
      width: 100%;
    }
  }
}

Then the scrolling

We’ve already set overflow-x on the .carousel, formally making it our scroll container. We are able to drop in slightly scroll snapping to ensure we’re solely scrolling one merchandise at a time.

.carousel {
  /* similar as earlier than */

  scroll-snap-type: x necessary;
  scroll-behavior: clean; /* non-obligatory for clean scrolling */
  scrollbar-width: none; /* non-obligatory to cover the scrollbar */
}

We wish to make it possible for the slides are aligned to the middle of the scroll container when snapping into place:

.carousel-slide {
  /* and so on. */
  scroll-snap-align: heart;
}

Right here’s what we’ve got up to now:

Subsequent, the animation

Right here’s the actually cool factor I discussed on the very begin: a view timeline animation is basically the identical factor as some other CSS animation you write with keyframes. On this case, we wish keyframes the place the carousel objects are small and blurry at the beginning and finish, however turn out to be bigger and clearer proper smack dab in the midst of the animation.

@keyframes slide {
  /* from begin to 45%, and to the tip (100%) */
  45%, 100% {
    rework: scale(0.5);
    border-radius: 20px;
    filter: blur(6px) brightness(.8);
  }
  /* center */
  50% {
    rework: scale(1);
    border-radius: 4px;
    filter: none;
  }
}

Appears to be like acquainted, proper? That is the form of CSS you’ve been writing without end! And guess what? We set the animation on the factor we’re animating simply as you usually would as nicely:

.carousel-slide {
  /* and so on. */
  animation: slide; 
}

The one distinction is that we wish the animation to run on a timeline based mostly on the factor’s present view() as a substitute of the common timeline. That’s the place the animation-timeline property comes into play:

.carousel-slide {
  /* and so on. */
  animation: slide; 
  animation-timeline: view(inline);
}

Now, technically talking, we might slap that timeline immediately within the animation shorthand property like some other constituent animation property, e.g., animation-name, animation-delay, animation-duration, and so on. However assigning a timeline perform this fashion isn’t supported by any browsers but. So, for now, your greatest wager is to declare it by itself. Simply you’ll want to declare it after the animation shorthand, or else it’s possible you’ll end up inadvertently overriding your view timeline with auto (the default property worth) as a substitute of view().

That completes our demo:

See that? All we’ve actually finished is ready a CSS animation that runs on components. Nonetheless, as a substitute of operating on the default timeline, the animation runs when a component scrolls out and in of view. That’s the distinction between commonplace and think about timelines.

view() vs. scroll()

However wait! It’s possible you’ll or could not know that view() timelines are half of a bigger characteristic set known as CSS Scroll-Pushed Animations. And view() isn’t the one perform supported by the animation-timeline property. We even have the scroll() perform.

The scroll() perform creates a scroll progress timeline that’s tied to the scroll place of a container, whereas view() creates a view progress timeline that’s based mostly on the visibility of a component inside its container.

Each capabilities are helpful in their very own methods! I usually assume view() is best for item-specific reveal results. So, for instance, if we wish to animate a slide solely as that particular slide scrolls into the scrollport, then the view() perform is the proper match. That’s why I’ve centered on it for our carousel instance — we wish to monitor a component’s place within the scrollport and run the animation accordingly.

Inset parameter and animation-range

You may additionally be questioning what the heck goes within the parentheses of the view() perform. It’s a perform, in any case, so it should settle for one thing in there, proper?

CSS view() takes two arguments: axis (block, inline, x, and y) and the inset. The inset parameter defines an offset from the scrollport’s edges inside which the animated factor is tracked. The official syntax appears like this:

animation-timeline: view( );

…which is merely a elaborate means of getting particular with precisely what areas of the scrollport we wish to set off the animation. For some animations, beginning and ending the timeline when factor totally enters and exits the scrollport could reduce issues off.

Two columns of list items. The width of the first item is 100% and each subsequent item in the list gets progressively shorter, creating an effect like a reversed staircase.

That’s no good! We wish every merchandise to completely slide in when it totally enters the scrollport, not when it totally exits. That’s why all of the objects look so staggered — they’re all at completely different factors within the view timeline.

That’s the place the inset parameter makes an enormous distinction. We could be extra particular about saying we wish every factor to start out animation when it comes up from the underside of the scrollport.

animation: slide-in linear each;
animation-timeline: view(100% 0%);

Ah, a lot significantly better:

The animation-range property works alongside comparable strains.

animation-range: entry; /* similar as: entry 0 entry 100%; */

The animation-range property accepts a slew of different key phrases, together with exit (when the factor leaves the scrollport), cowl (when the factor begins to enter begins to depart the scrollport), and include (when the factor totally enters then totally leaves the scrollport), amongst others. Geoff has revealed a bunch of notes and examples wanting particularly at every one.

Usually, carousels use results like fade in-and-out, scaling, and parallax. Nonetheless, since most CSS properties are animate-able, and even those that aren’t could be tricked into being so utilizing registered CSS properties (like within the case of gradient strains), you’ve gotten the choice to discover extra artistic methods of utilizing view() for carousels.

Right here’s an instance the place an animation of simply the background place creates a pleasant motion in a carousel.

Related Articles

Latest Articles