CSS Animation

CSS animationsopen in new window makes it possible to animate transitions between multiple CSS style configurations. The transition property can be seen as a simple animation, however it is limited to only two states start and end. The animation property on the other hand allows us to add multiple states.

Animations consist of two components:

  • Set of keyframes that indicate the start and end states of the animation’s style, as well as possible intermediate waypoints.
  • CSS animation property that is added to the element to which we intend to apply the animation on.

Keyframes

The @keyframesopen in new window 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.

  • The keyframes are defined using the @keyframe rule followed by a name of the sequence.
  • @keyframe rule may contain only two states from{ } and to{ } or may contain multiple states defined by percentage 0%{ } 10%{ } 20%{ } .... 100%{ }
  /* using from and to only */
  @keyframes changeBg{
    from{
      background-color: red;
    }
    to{
      background-color: blue;
    }
  }
  /* using percentage to have multiple waypoints */
  @keyframes transformElement{
    0%{
      transform: translateX(100px);
    }
    50%{
      transform: translateX(100px) rotate(45deg);
    }
    100%{
      transform: translateX(100px) rotate(-90deg);
    }
  }

Animation Properties

The purpose of 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 element.

The following properties can be used:

animation-name

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

animation-duration

The animation-durationopen in new window property configures the length of time that an animation should take to complete one cycle.

 @keyframes changeBg{
    from{
      background-color: red;
    }
    to{
      background-color: blue;
    }
  }
  .box{
    animation-name: changeBg;
    animation-duration: 1s;
  }








 
 
 
 

Note

animation-name and animation-duration are the two required properties to be added to an element for the animation to work.

animation-timing-function

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

animation-delay

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

animation-iteration-count

The animation-iteration-countopen in new window 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-modeopen in new window property defines what CSS values are applied to the element before and after the animation has executed.

animation-play-state

The animation-play-stateopen in new window 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 Lifeopen in new window gave us the 12 basic principles of animationopen in new window, 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 customize the animation-direction, animation-timing-function and the animation-fill-mode properties.

The animation-direction property allows us to set, through what direction of 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/open in new window, 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.