Chaining animations in CSS3

CSS3 animations are cool, but I’ve never really understood how to chain the same animation together on different elements.

I was recently playing around creating a loading animation which lead to me figuring it out. In this example I’m going to animate a series of dots that each flash in turn.

First up here’s the HTML I’ll be using:

<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>

and the basic CSS to go with it:

.dot {
    display: inline-block;
    background: #CCC;
    height: 8px;
    width: 8px;
    border-radius: 12px;
    margin-right: 5px;
}
.dot:first-child {
    background: black;
}

This produces:

Intials Dots

The next thing we need to do is create the animation that will highlight the dots:

@keyframes flash {
    from  {
        background: black;
    }
    to {
        background: #CCC;
    }
}

This is pretty basic & simply flashes the dot from black to grey.

Now we’ll get the dots to use this animation:

.dot {
    ...

    animation-name: flash;
    animation-duration: 2000ms;
    animation-iteration-count: infinite;

    /** or in short hand **/
    animation: flash 2000ms infinite;
}

This runs the flash animation on the dot element continuously (infinite) at a speed of 2 seconds. This produces the following:

Animated dots, all flashing

This isn’t quite what we want because each dot is flashing at the same time. Enter animation-delay.

.dot:nth-child(2) {
    animation-delay: 500ms;
}
.dot:nth-child(3) {
    animation-delay: 1000ms;
}

animation-delay stops the animation from running until the set time after the element is loaded. In our example the second dot will flash after 500ms & the third after 1000ms, this keeps the dots out of sequence & produces the effect we want:

Dots flashing in sequence

The trick here is to keep the animations from running at the same time. In this example the first dot will begin animating at:

  • 0 seconds
  • 2 seconds
  • 4 seconds …

the second at:

  • 0.5 seconds
  • 2.5 seconds
  • 4.5 seconds …

and the third at:

  • 1 seconds
  • 3 seconds
  • 5 seconds …

This means that the never begin animating at the same time & will therefore appear chained together.

To see this fully in action see this pen.

Since animations are also supported on pseudo-elements it’s also possible to shrink the html for this by using :after & :before, like so:

<div class="dots"></div>
.dots {
    display: inline-block;
    background: black;
    height: 8px;
    width: 8px;
    border-radius: 12px;
    position: relative;
    animation: flash 2000ms infinite;
}
.dots:before, .dots:after {
    content: '';
    position: absolute;
    left: 16px;
    background: #CCC;
    height: 8px;
    width: 8px;
    border-radius: 12px;
    animation: flash 2000ms 500ms infinite; /* 500ms is the delay */
}
.dots:after {
    left: 32px;
    animation-delay: 1000ms;
}

Finally, because mutiple animations can be used on an element you can go a bit crazier with something like this.

Comments

blog comments powered by Disqus

About ParkJi

Me!

My name is Ben Parker, I'm a 27 year old front end web developer with a passion for web design, standards & new & innovative technologies.