CSS Animation

CSS animations make it possible to animate transitions from one CSS style configuration to another. Animations consist of two components, a style describing the CSS animation and a set of keyframes that indicate the start and end states of the animation’s style, as well as possible intermediate waypoints.

Keyframes

The @keyframes CSS at-rule controls the intermediate steps in a CSS animation sequence by defining styles for keyframes (or waypoints) along the animation sequence. This gives more control over the intermediate steps of the animation sequence than transitions.

Animation Properties

The purpose the animation property is not to describe the appearance of the animation, that is the job of the @keyframes CSS at-rule, but to describe how those rules should be applied on the target elements.

The following properties can be used:

animation-name

The animation-name property specifies the name of the @keyframes at-rule describing the animation’s keyframes.

animation-duration

The animation-duration property configures the length of time that an animation should take to complete one cycle.

animation-timing-function

The animation-timing-function property configures the timing of the animation; that is, how the animation transitions through keyframes, by establishing acceleration curves.

animation-delay

The animation-delay property sets a delay between the time the element is loaded and the beginning of the animation sequence.

animation-iteration-count

The animation-iteration-count property defined the number of times the animation should repeat; you can specify infinite to repeat the animation indefinitely.

animation-direction

The [animation-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction) property set the direction in which animation will run through the keyframes of the@keyframes` at-rule.

animation-fill-mode

The animation-fill-mode property defines what CSS values are applied to the element before and after the animation has executed.

animation-play-state

The animation-play-state determines whether the animation is running or paused

Creating CSS Animations

A simple animation

Generally, the first step to creating a CSS animation is to create the keyframes. We need to create two or more keyframes to define a start and end state. At a minimum, we specify a name for our animation following the @keyframes keyword then define our start and end points.

In the example below, we use the from and to keywords to declare the start and end states.

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

Once keyframes are created, we can apply it to an element using the animation-properties. The animation-name and animation-duration are the only required animation-properties.

.rotate {
  animation-name: rotate;
  animation-duration: 1s;
}

A jumping box

The famous book The Illusion of Life gave us the 12 basic principles of animation, and while the book was derived these principles from the work of the Disney animator, they can still be applied to the CSS animations. However, to create believable animations you have to understand how to use the different animation properties effectively.

To create the effects of squishing and squashing often requires using the transform property in subtle ways. In the example below, the box will jump, but no effort was made to make it realistic.

@keyframes jump {
  50% {
    transform: translate(0, -200px);
  }
}

While animation was achieved, it was not very realistic. The following version using the transform scale() function was used to make the animation more appealing.

@keyframes jump {
  10%,
  25% {
    transform: scale(1.3, 0.7);
  }

  50% {
    transform: scale(0.5, 2) translate(0, -200px);
  }

  60% {
    transform: scale(1, 1) translate(0, 0);
  }

  75% {
    transform: scale(1.3, 0.7) translate(0, 0);
  }

  85% {
    transform: scale(1, 1) translate(0, 0);
  }
}

A pendulum

For this next example, we will simulate a pendulum swinging back and forth. This example will customizing the animation-direction, animation-timing-function and the animation-fill-mode properties.

The animation-direction property allows us to set what direction through the keyframes we want the animation to go, normal (0% to 100%), reverse (100% to 0%), or alternate, which alternate between normal or reverse between each animation cycle.

The animation-fill-mode can be confusing for beginners, but all it does is determine which styles should be set before and after an animation is executed. For example, if animation-fill-mode is set to backwards the first keyframe will be applied to the element before the animation begins, and if the animation-fill-mode is set to forwards the last keyframe will be applied to the element after the animation has ended.

NOTE

The value forwards will have no effect on an animation with an iteration-count of infinite, because the animation never ends.

In this first example, we are not customizing the animation-direction, animation-fill-mode or the animation-timing-function.

NOTE

To create the pendulum animation, we adjust the transform-origin property to move the transformation point 100px above the block.

@keyframes swing {
  /* These styles will be applied throughout the animation */
  0%,
  100% {
    border-radius: 50%;
    transform-origin: 0 -100px;
  }

  0% {
    transform: rotate(77deg);
  }

  100% {
    transform: rotate(-45deg);
  }
}

.swing {
  animation-name: swing;
  animation-duration: 2s;
  animation-delay: 2s;
  animation-iteration-count: infinite;
}

Now, lets add animation-fill-mode and animation-direction.






















 
 



@keyframes swing {
  /* These styles will be applied throughout the animation */
  0%,
  100% {
    border-radius: 50%;
    transform-origin: 0 -100px;
  }

  0% {
    transform: rotate(77deg);
  }

  100% {
    transform: rotate(-45deg);
  }
}

.swing {
  animation-name: swing;
  animation-duration: 2s;
  animation-delay: 2s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-fill-mode: backwards;
}

The animation looks better, but the timing is off.

Timing is so important for creating believable animations. If the timing is not right the whole animation will look... off. We can control the timing of an animation with the animation-timing-function property. This property sets the speed curve of the animation, which is how fast through the keyframes the animation is going at any time during the animation cycle. For example, Is the animation simulating going down a hill, starting off slow and end moving fast (ease-in) or is it coming to a stop from high speed (ease-out)?

CSS includes several pre-built speed curves which can be accessed using the following keywords: ease, ease-in, ease-out, ease-in-out, and linear. While these pre-built options are convenient, they can also be limiting. That is why there is also the cubic-bezier() function, which will allow you to create your own speed curve. There are even cubic bezier generators, like https://cubic-bezier.com/, which can help you create just the right timing.

Lets customize the timing function of our pendulum to make it flow more naturally. Fortunately, we can use one of the pre-built options ease-in-out.
























 



@keyframes swing {
  /* These styles will be applied throughout the animation */
  0%,
  100% {
    border-radius: 50%;
    transform-origin: 0 -100px;
  }

  0% {
    transform: rotate(77deg);
  }

  100% {
    transform: rotate(-45deg);
  }
}

.swing {
  animation-name: swing;
  animation-duration: 2s;
  animation-delay: 2s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
  animation-fill-mode: backwards;
  animation-timing-function: ease-in-out;
}

A wave

In this final example, we will learn how an animation added to multiple elements can create a totally new effect, and we will accomplish this by using the animation-delay property.

In this first example, we have applied a simple animation to multiple elements.

@keyframes wave {
  0%,
  50%,
  100% {
    background-color: orange;
    transform: scale(1);
  }
  25% {
    background-color: yellow;
    transform: scale(1, 2);
  }
  75% {
    background-color: red;
    transform: scale(1, 0.5);
  }
}

.wave {
  animation-name: wave;
  animation-duration: 2s;
  animation-iteration-count: infinite;
}

Now, lets add a delay to animation, increasing the delay time for each element.






















 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 



@keyframes wave {
  0%,
  50%,
  100% {
    background-color: orange;
    transform: scale(1);
  }
  25% {
    background-color: yellow;
    transform: scale(1, 2);
  }
  75% {
    background-color: red;
    transform: scale(1, 0.5);
  }
}

.wave {
  animation-name: wave;
  animation-duration: 2s;
  animation-iteration-count: infinite;
}

.wave:nth-child(1) {
  animation-delay: 0.2s;
}

.wave:nth-child(2) {
  animation-delay: 0.4s;
}

.wave:nth-child(3) {
  animation-delay: 0.6s;
}

.wave:nth-child(4) {
  animation-delay: 0.8s;
}

.wave:nth-child(5) {
  animation-delay: 1s;
}

Once again, our timing is off. So, let us go back and add different timing function, linear.




















 
























@keyframes wave {
  0%,
  50%,
  100% {
    background-color: orange;
    transform: scale(1);
  }
  25% {
    background-color: yellow;
    transform: scale(1, 2);
  }
  75% {
    background-color: red;
    transform: scale(1, 0.5);
  }
}

.wave {
  animation-name: wave;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

.wave:nth-child(1) {
  animation-delay: 0.2s;
}

.wave:nth-child(2) {
  animation-delay: 0.4s;
}

.wave:nth-child(3) {
  animation-delay: 0.6s;
}

.wave:nth-child(4) {
  animation-delay: 0.8s;
}

.wave:nth-child(5) {
  animation-delay: 1s;
}

Further Review

Review the following material and be sure to download the lesson file to begin exploring animations.

References

Reach Ahead

This YouTube video was created by Steve Griffith.