Kevin Bishop | How to Code Cool CSS Animations

How to Code Cool CSS Animations


  • 20 Apr


  • KevinBish

This tutorial is an introduction to coding cool CSS animations using HTML and CSS. It’s meant for those who already have a good understanding of HTML and CSS, with some familiarity with Sass.

From what I’ve found, the most challenging part isn’t understanding the code but rather learning how to experiment. That’s why it is important to have real-time visual feedback when coding a CSS animation. I prefer to use a browser-based editor that refreshes automatically as I code. (I recommend CodePen!)

Using CSS keyframes, animation delays, and CSS transforms, we’ll create a simple yet interesting CSS animation. Let’s get started!

 
 
 
 
 
 
 
 

1

Create an HTML element to animate

Start with a single element. This will form the basis of the CSS animation. To make it easier to manage the animation as a whole, create a wrapper element and set position: absolute on the elements inside.

.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 100%;
  background-color: turquoise;
}
<div class="animation-wrapper">
  <div class="circle"></div>
</div>

2

Repeat the element to create a pattern

Duplicate the element, then use a Sass loop to space them out. Each can be targeted using the :nth-child selector. To spread the elements out, I’m setting the left property instead of transform: translate() because the transform property will be set as part of the animation later and I don’t want to overwrite it.

.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 100%;
  background-color: turquoise;
}

 .circle:nth-child(1) {
	 left: 0px;
	 animation-delay: 0.1s;
}
 .circle:nth-child(2) {
	 left: 30px;
	 animation-delay: 0.2s;
}
 .circle:nth-child(3) {
	 left: 60px;
	 animation-delay: 0.3s;
}
 .circle:nth-child(4) {
	 left: 90px;
	 animation-delay: 0.4s;
}
 .circle:nth-child(5) {
	 left: 120px;
	 animation-delay: 0.5s;
}
 .circle:nth-child(6) {
	 left: 150px;
	 animation-delay: 0.6s;
}
 .circle:nth-child(7) {
	 left: 180px;
	 animation-delay: 0.7s;
}
 .circle:nth-child(8) {
	 left: 210px;
	 animation-delay: 0.8s;
}
<div class="animation-wrapper">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

3

Add motion using CSS keyframes

Keep it simple here. I’ve found the best way to start adding motion is to create keyframes and animation the transform property. In this example, I’m animating transform: translate(). For the keyframes, I start by keeping it to one or two steps and adding more in later.

.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 100%;
  background-color: turquoise;
  animation: move-the-circle 1s infinite;
  transform-origin: center center;
}

 .circle:nth-child(1) {
	 left: 0px;
	 animation-delay: 0.1s;
}
 .circle:nth-child(2) {
	 left: 30px;
	 animation-delay: 0.2s;
}
 .circle:nth-child(3) {
	 left: 60px;
	 animation-delay: 0.3s;
}
 .circle:nth-child(4) {
	 left: 90px;
	 animation-delay: 0.4s;
}
 .circle:nth-child(5) {
	 left: 120px;
	 animation-delay: 0.5s;
}
 .circle:nth-child(6) {
	 left: 150px;
	 animation-delay: 0.6s;
}
 .circle:nth-child(7) {
	 left: 180px;
	 animation-delay: 0.7s;
}
 .circle:nth-child(8) {
	 left: 210px;
	 animation-delay: 0.8s;
}

@keyframes move-the-circle {
  0% {
    transform: translate(0, 0);
  }
  50% {
    transform: translate(0, 50px);
  }
  100% {
    transform: translate(0, 0);
  }
}
<div class="animation-wrapper">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

4

Stagger the motion using CSS animation delay

Using the same Sass loop as before, set the animation-delay property to be slightly offset for each element. This instantly makes the CSS animation dramatically more interesting.

.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 100%;
  background-color: turquoise;
  animation: move-the-circle 1s infinite;
  transform-origin: center center;
}

 .circle:nth-child(1) {
	 left: 0px;
	 animation-delay: 0.1s;
}
 .circle:nth-child(2) {
	 left: 30px;
	 animation-delay: 0.2s;
}
 .circle:nth-child(3) {
	 left: 60px;
	 animation-delay: 0.3s;
}
 .circle:nth-child(4) {
	 left: 90px;
	 animation-delay: 0.4s;
}
 .circle:nth-child(5) {
	 left: 120px;
	 animation-delay: 0.5s;
}
 .circle:nth-child(6) {
	 left: 150px;
	 animation-delay: 0.6s;
}
 .circle:nth-child(7) {
	 left: 180px;
	 animation-delay: 0.7s;
}
 .circle:nth-child(8) {
	 left: 210px;
	 animation-delay: 0.8s;
}

@keyframes move-the-circle {
  0% {
    transform: translate(0, 0);
  }
  50% {
    transform: translate(0, 50px);
  }
  100% {
    transform: translate(0, 0);
  }
}
<div class="animation-wrapper">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

5

Experiment with different values and properties

This is where the fun comes in! In the @keyframes block, what happens when you change the background-coloropacity, and scale() of the element? By experimenting with different values and properties, you can create many variations using the same basic setup. Try adding in more keyframe steps, adjusting the timing, and changing values until you create something cool and new.

.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 100%;
  background-color: turquoise;
  animation: move-the-circle 1s infinite;
  transform-origin: center center;
}

 .circle:nth-child(1) {
	 left: 0px;
	 animation-delay: 0.1s;
}
 .circle:nth-child(2) {
	 left: 30px;
	 animation-delay: 0.2s;
}
 .circle:nth-child(3) {
	 left: 60px;
	 animation-delay: 0.3s;
}
 .circle:nth-child(4) {
	 left: 90px;
	 animation-delay: 0.4s;
}
 .circle:nth-child(5) {
	 left: 120px;
	 animation-delay: 0.5s;
}
 .circle:nth-child(6) {
	 left: 150px;
	 animation-delay: 0.6s;
}
 .circle:nth-child(7) {
	 left: 180px;
	 animation-delay: 0.7s;
}
 .circle:nth-child(8) {
	 left: 210px;
	 animation-delay: 0.8s;
}

@keyframes move-the-circle {
  0% {
    transform: translate(0, 0) scale(1);
    opacity: 1;
    background-color: turquoise;
  }
  50% {
    transform: translate(0, 50px) scale(.4);
    opacity: .5;
    background-color: blue;
  }
  100% {
    transform: translate(0, 0) scale(1);
    opacity: 1;
    background-color: turquoise;
  }
}
<div class="animation-wrapper">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>