DEV Community

Nic
Nic

Posted on • Originally published at blog.nicm42.co.uk on

Scroll Timeline

This is an exciting new thing that's currently only available in Chrome and Edge. It allows you to scroll elements on the page as you scroll the page. Previously, the only way to do it was to use an Intersection Observer. But this doesn't use JS at all.

Some set up

I'm starting with a box in the middle of the page (vertically) and on the left. I've made the body twice the height of the browser window to make sure you can scroll and therefore see the effect.

<div class="box"></div>
Enter fullscreen mode Exit fullscreen mode
html {
  overflow-x: clip;
}

body {
  height: 200vh;
  position: relative;
  display: flex;
  align-items: center;
}

.box {
  width: 200px;
  height: 200px;
  background-color: pink;
  position: absolute;
  left: 0;
}
Enter fullscreen mode Exit fullscreen mode

I'm going to move the box from the left of the screen to the right, hence the need to stop the horizontal scrollbar from showing.

Scroll-timeline

Most of the set up for the animation is a standard animation:

.box {
  animation: slide-right linear forwards;
}

@keyframes slide-right {
  to { 
    left: 100%;
 }
}
Enter fullscreen mode Exit fullscreen mode

So we're moving the box from left: 0 to left: 100%. So far so normal. But the animation is missing the time. That's because we want it to move as we scroll, which could take any amount of time. There are only two things to add to get it to work.

.box {
 animation-timeline: view();
 animation-range: entry exit;
}
Enter fullscreen mode Exit fullscreen mode

Both of these together are our timing function.

animation-timeline: view() means that as soon as the element is visible it's in view and as soon as it's not visible it's not in view.

animation-range: entry exit means that the animation should start once the element enters the viewport and should stop when it leaves.

What this all means is that as you scroll the page the box moves across the page - and also appears to move up since there is nothing else on the page to compare its position to.

Final code

Here is the whole code in CodePen:

Other considerations

If you open this CodePen in Firefox right now, you'll see the box is over to the right. This is because it's run the animation - since we didn't specify a time it took no time at all.

The solution to this is to wrap the animation in a supports query - this means that if the browser doesn't support it, the box will just stay where it started as you scroll.

.box {
  width: 200px;
  height: 200px;
  background-color: pink;
  position: absolute;
  left: 0;
}

@supports (animation-timeline: view()) {
  .box {
    animation: slide-right linear forwards;
    animation-timeline: view();
    animation-range: entry exit;
  }
}
Enter fullscreen mode Exit fullscreen mode

You also need to consider people for whom animation is a problem. This is easy, because you can wrap the whole animation in a prefers-reduced motion media query:

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .box {
      animation: slide-right linear forwards;
      animation-timeline: view();
      animation-range: entry exit;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

And just like that, the animation will only run if the browser supports it and the user hasn't turned on reduced motion settings.

Top comments (0)