animation-iteration-delay hack

While there is no such property as an `animation-iteration-delay`, you can employ the `animation-delay` property, incorporate delays within your keyframe declaration, or use JavaScript to fake it. The best method for ‘faking it’ depends on the number of iterations, performance, and whether the delays are all equal in length.

What is an animation iteration delay? Sometimes you want an animation to occur multiple times, but want to wait a specific amount of time between each iteration.

Let’s say you want your element to grow 3 times, but want to wait 4 seconds between each 1s iteration. You can include the delay within your keyframe definition, and iterate through it 3 times:

.animate3times {
    background-color: red;
    animation: yellow;
    animation-iteration-count: 3;
    animation-duration: 5s;
 }
@keyframes yellow {
 80% {
    transform: scale(1);
    background-color:red;
  }
  80.1% {
    background-color: green; 
    transform: scale(0.5);
  }
  100% {
    background-color: yellow;
    transform: scale(1.5);
  }
 }

Note the first keyframe selector is at the 80% mark, and matches the default state. This will animate your element 3 times, staying in the default state for 80% of the 5 second animation, or for 4 seconds, and moving from green to yellow and small to big over the last 1 second of the animation duration, before iterating again, stopping after 3 iterations.

This method works for infinite repetitions of the animation as well. Unfortunately, it is only a good solution if the iteration delay between each iteration is identical. If you want to change the delay between each iteration, while not changing the duration of the change in size and color, you have to write a new @keyframes definition.

To enable different iteration delays between animations, we could create a single animation and bake in the effect of three different delays:

.animate3times {
    background-color: red;
    animation: yellow;
    animation-iteration-count: 1;
    animation-duration: 15s;
 }
@keyframes yellow {
  0%, 13.32%, 20.01%, 40%, 46.67%, 93.32% {
    transform: scale(1);
    background-color:red;
  }
  13.33%, 40.01%, 93.33% {
    background-color: green; 
    transform: scale(0.5);
  }
  20%, 46.66%, 100% {
    background-color: yellow;
    transform: scale(1.5);
  }
 }

This method may be more difficult to code and maintain. It works for a single cycle of the animation. To change the number of animations or the iteration delay durations, another keyframe declaration would be required.

The animation-iteration-delay hack

There’s a solution that currently works that is not specifically allowed in the animation specification, but it isn’t disallowed, and it’s supported: you can declare an animation multiple times, each with a different animation-delay.

.animate3times {
    animation: yellow, yellow, yellow;
    animation-delay: 0, 4s, 10s;
    animation-duration: 1s;
 }
@keyframes yellow {
  0% {
    background-color: green; 
    transform: scale(0.5);
  }
  100% {
    background-color: yellow;
    transform: scale(1.5);
  }
 }

See http://codepen.io/estelle/pen/PqRwGj.

We’ve attached the animation three times, each with a different delay. In this case, each animation iteration concludes before the next one proceeds. If they overlap, while they’re concurrently animating, the values will be the values from the last declared animation.

See http://codepen.io/estelle/pen/gpemWW

Of course, you can also use JavaScript with animationstart, animationiteration and animationend eventlisteners that add or remove animation names or classes from your element.

Published by

Estelle Weyl

My name is Estelle Weyl. I an open web evangelist and community engineer. I'm a consulting web developer, writing technical books with O'Reilly, running frontend workshops, and speaking about web development, performance, and other fun stuff all over the world. If you have any recommendations on topics for me to hit, please let me know via @estellevw.

One thought on “animation-iteration-delay hack”

Comments are closed.