Introduction

We have already learned how 2D and 3D animations work. But, there's a lot of animation sub-properties. Each one has its use cases and affects your animation in different ways. So, today we're going to go through all of them. Let's get started!

Getting Started

Here I have a simple project structure with an index.html file and a styles folder and we already have applied a simple boilerplate template and added the animations.css file which has some basic style for our example elements. We also added normalize.

<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" type="text/css" href="styles/normalize.css">
  <link rel="stylesheet" type="text/css" href="styles/animations.css">
  <title>Css Animation</title>
</head>
<body>
  <div class="container">
    <div class="blue-square"></div>
    <div class="red-square"></div>
  </div>
</body>
</html>

Ok, here we have two animations, move and bounce, and a couple of squares, which are going to be our example elements. Both of them have the animations applied. Just like we've previously done.

  .container {
    padding: 5rem;
    width: 30rem;
  }

  .blue-square,
  .red-square {
    height: 5rem;
    width: 5rem;
  }

  .blue-square {
    animation: move 2s alternate infinite;
    background: lightblue;
  }

  .red-square {
    animation: move 2s alternate infinite;
    background: red;
    margin-top: 2rem;
  }

  @keyframes move {
    from {
      margin-left: 0;
    }
    to {
      margin-left: 10rem;
    }
  }

  @keyframes bounce {
    0%, 20%, 40%, 60%, 80%, 100% {
      transform: translateY(1rem) ;
    }
    10%, 30%, 50%, 70%, 90% {
      transform: translateY(0rem);
    }
  }

First, let's change all the values from the shorthand property to its individual version.

  .blue-square {
    animation-name: move;
    animation-duration: 2s;
    animation-direction: alternate;
    animation-iteration-count: infinite;
    background: lightblue;
  }

Until now we've been applying the animation name using the shorthand property, but we have an important advantage if we use animation-name. We can set various animations, let's add an animation to our .blue-square and see what happens.

  .blue-square {
    animation-name: move, bounce;
    animation-duration: 2s;
    animation-direction: alternate;
    animation-iteration-count: infinite;
    background: lightblue;
  }

See what's happening now? We have both animations working at the same time. This can be really useful when making complicated animations. We can also set different times using animation-duration. Let's see what happens if we apply a different duration to our .bounce in the .blue-square.

  .blue-square {
    animation-name: move, bounce;
    animation-duration: 2s`, 5s;
    animation-direction: alternate;
    animation-iteration-count: infinite;
    background: lightblue;
  }

And look what's happening now, the bounce is slower than before. If we want our animation to start at a certain time, we can use animation-delay. This property allow us to set a delay timer before our animation starts. animation-delay also accepts negative values, in this case the specified value will be taken directly from the animation duration, which means if we set animation-delay: -1s and animation-duration: 5s, the animation will start in 4 seconds. Let's see how the delay affects our `.blue-square css .blue-square { animation-name: move, bounce; animation-delay: 3s; animation-duration: 2s`, 5s; animation-direction: alternate; animation-iteration-count: infinite; background: lightblue; } As you can see, the element now starts the animation 3 seconds after the other element. Now let's change the value for a negative one. css .blue-square { animation-name: move, bounce; animation-delay: -3s; animation-duration: 2s`, 5s; animation-direction: alternate; animation-iteration-count: infinite; background: lightblue; } And now the animation starts in the half of the second iteration. We can play with different values, and set different starts for our animations. In our previous examples, we used animation-direction: normal and alternate, but there are a couple more, reverse and alternate-reverse, look what happens if we set reverse. css .blue-square { animation-name: move; animation-duration: 2s; animation-direction: reverse; animation-iteration-count: infinite; background: lightblue; } The animation starts from the final state to the initial state. And, alternate-reverse works just like alternate but has the same inverted start. It's important to keep in mind that all of the animation sub-properties can accept multiple values separated by commas. This means we can apply different values of each sub-property to each animation we may have defined. There are cases when we want to maintain the styles from the animation. Don't worry we have a property for that, animation-fill-mode, which specifies how the styles defined in the animation are applied during the delay time (or permanently if we didn't set any delay and aren't using alternate). We have three important values forwards, backwards and both. Let's play with each of them, and see how they affect our element. css .blue-square { animation-name: move; animation-duration: 2s; animation-direction: normal; animation-fill-mode: forwards; animation-iteration-count: 1; background: lightblue; } .red-square { animation: move 2s reverse 1; animation-fill-mode: backwards; background: red; margin-top: 2rem; } See what's happening? If we set animation-fill-mode: forwards; the element maintains the styles defined in the final state of the animation. Then, if we set animation-fill-mode: backwards;, the element maintains the styles defined in the initial state of the animation. But what if we want to pause and play the animation? We have a property for that animation-play-state. Let's see what happens if we use paused in one of our elements. css .blue-square { animation-name: move; animation-duration: 2s; animation-direction: normal; animation-iteration-count: infinite; animation-play-state: paused; background: lightblue; } The element is paused, and if I change to running the animation starts. The important thing to keep in mind is that once we change the value to running the animation will start from the point where it was paused. We already know how animation-iteration-count works. So, there's just one sub-property left and that's animation-timing-function. This property modifies the time between transitions, and how we see them. First, let's see the difference between the basic values linear and ease-in / ease-out css .blue-square { animation-name: move; animation-duration: 2s; animation-direction: alternate; animation-iteration-count: infinite; animation-timing-function: linear; background: lightblue; } .red-square { animation: move 2s alternate infinite; animation-fill-mode: backwards; animation-timing-function: ease-in; background: red; margin-top: 2rem; } If we set ease-in, the animation initial state is slower than the final state, and if we set ease-out the final state is slower than the initial state. We can also define how many steps the animation should be done in. Let's see how can we do this. css .blue-square { animation-name: move; animation-duration: 2s; animation-direction: alternate; animation-iteration-count: infinite; animation-timing-function: steps(6, end); background: lightblue; } See how it works now? The animation is done in 6 steps. We can even define how many seconds every transition should last. css .blue-square { animation-name: move; animation-duration: 2s; animation-direction: alternate; animation-iteration-count: infinite; animation-timing-function: cubic-bezier(0.5, 0.2, 2.0, 0.4); background: lightblue; } And now all the transitions are completely irregular. There are a lot of possibilities, and it's up to you on how to implement it. ### Summary Today we learned how all the animation sub-properties work, and how they affect the animations we define in our apps. See you in the next video!