Starting CSS Animations Mid-Way

Avatar of Chris Coyier
Chris Coyier on

📣 Freelancers, Developers, and Part-Time Agency Owners: Kickstart Your Own Digital Agency with UACADEMY Launch by UGURUS 📣

Say you have a @keyframe animation that animates an element all the way across the screen. From off the left edge to off the right edge. You apply it to multiple elements. But you don’t want all the elements to start at the same exact position.

You can change the animation-delay so that they start at different times, but they will still all start at the same place.

Fortunately, there is a way.

The trick is to use negative animation-delay. That will begin an animation right away, but as if part of the animation has run already.

For instance, here’s three elements:

<div class="thing thing-1"></div>
<div class="thing thing-2"></div>
<div class="thing thing-3"></div>

They are 300px wide. We’re going to animate them all the way across the screen:

@keyframes moveAcross {
  0% {
    left: -300px;
  }
  100% {
    left: 100%;
  }
}

They all use this animation, meaning they would all start at the same place:

.thing {
  width: 300px;
  position: absolute;
  top: 0;
  left: 0;
  animation: moveAcross 10s linear infinite;
}

To change them to start at different place along the keyframe timeline, we apply those negative delays:

.thing-1 {
  animation-delay: -1s;
}
.thing-2 {
  animation-delay: -2s;
}
.thing-3 {
  animation-delay: -3s;
}

Another little trick: to test those starting positions, just stop the animation (you’ll essentially just be seeing the first frame):

.car {
  ...
  animation-play-state: paused;
}
Paused
Running

This probably comes in most useful with really slow animations where a straight delay would result in nothing or the wrong thing being shown too long.

For fun, different durations as well:

See the Pen hjbKp by Chris Coyier (@chriscoyier) on CodePen.