A Guide to CSS Animation - Part 2
Tags: css, animation, beginners, webdev
Published: 2019-12-20 18:21:41

Hey! You’re back 🙌

In [part 1](https://dev.to/jh3y/a-guide-to-css-animation-part-1-36o9), we got things moving. Now we will dig into applying animations. We already introduced `animation-name` and `animation-duration`, but there’s much more to look at.

Don’t forget, all the code is available in the following CodePen collection 👍 That way you can edit and play around with the examples.

[![Link to CodePen collection of demos](https://thepracticaldev.s3.amazonaws.com/i/jqssaberzcdexpoqwzce.png)](https://codepen.io/collection/nMpBQm/)

# animation-iteration-count

Let’s pick up from where we left off with by modifying our first animation. If you need a little refresher, this is what we had.

![A basic animation of a div spinning round once](https://thepracticaldev.s3.amazonaws.com/i/rn1988hobz0eed6n8o9x.gif)

But the animation only ran once. What if we wanted the animation to run many times or never stop? In the case of loading animations, we may want the animation to be infinite. This is where `animation-iteration-count` comes into play.

Let’s say we wanted the animation to run five times giving us ten seconds of animation.

```css
div {
  animation-duration: 2s;
  animation-name: spin;
  animation-iteration-count: 5;
}
```


It’s that easy! Let’s turn our spinning square into a loading spinner. To do this, `animation-iteration-count` also accepts the keyword `infinite` 👍

```css
div {
  animation-duration: 2s;
  animation-name: spin;
  animation-iteration-count: infinite;
}
```

Which gives us the following 🎉

{% codepen https://codepen.io/jh3y/pen/aKZZNY %}

# animation-timing-function

Let’s take another look at that spinning square. The square does keep on spinning. But not without a little break after every spin. This is due to the `animation-timing-function`.

![Our animated square infinitely spinning with a pause after each iteration](https://thepracticaldev.s3.amazonaws.com/i/rn1988hobz0eed6n8o9x.gif)

The `animation-timing-function` property defines the speed characteristics of an animation. It accepts a few different values.

- `cubic-bezier(x1, y1, x2, y2)` - provides ability to define custom speed
- `ease` - start and end slowly but speedier in the middle(default)
- `ease-in` - start slowly
- `ease-in-out` - start and end slowly but not the same as ease
- `ease-out` - end slowly
- `linear` - maintain speed throughout
- `steps(number, direction <optional>)` - provides a way to split the animation into equal steps. `direction` values can either be `start` or `end`. `start` means that the first step happens at the start of the animation. `end` means that the last step happens at the end of the animation. `end` is the default value.

So which one do you choose? Different scenarios will call for different easing. The following is a nice short resource about the basics of easing.

[![Link to MDN article on animation easing](https://thepracticaldev.s3.amazonaws.com/i/m9sxsjqqwi46bhez4fhu.png)](https://developers.google.com/web/fundamentals/design-and-ux/animations/the-basics-of-easing)

You can experiment with different easings to find what feels right in your applications. This pen shows how `animation-timing-function` can affect the same animation.

{% codepen https://codepen.io/jh3y/pen/JZKReG %}

The ease that might be trickier to grasp is `cubic-bezier`. In essence, the `cubic-bezier` function defines a cubic bezier curve. There is a good explanation of the `cubic-bezier` function in this article.

[![Link to MDN article on animation timing function](https://thepracticaldev.s3.amazonaws.com/i/5gs0l8ixb0ovddwbu45e.png)](https://developer.mozilla.org/en-US/docs/Web/CSS/timing-function)

Or, you may prefer to play with the `cubic-bezier` function and compare it to the other easing values. [cubic-bezier.com](https://cubic-bezier.com) has you covered 👍

-------------

So returning to our spinning square. How do we remove that little break? 
We can apply `linear` timing to replace the default `ease` timing.

```css
div {
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-name: spin;
  animation-timing-function: linear;
}
```

This would give us

{% codepen https://codepen.io/jh3y/pen/OEXRRm %}

Sweet 🍭

# animation-play-state

Play state is pretty simple. You can pause animations or have them running. We use the `animation-play-state` property to control this. For our spinning square we could introduce a checkbox that toggles the play state. Using the sibling selector, we can toggle the play state 👍

```css
div {
  animation-duration: 2s;
  animation-iteration-count: infinite;
  animation-name: spin;
  animation-play-state: paused;
  animation-timing-function: linear;
}

:checked ~ div {
  animation-play-state: running;
}
```

When it’s `:checked` we set the play state to `running` 👟

{% codepen https://codepen.io/jh3y/pen/zaBVgJ %}

# animation-delay

Next up is delaying animations. Like `animation-duration`, `animation-delay` takes a time value in milliseconds or seconds.

Let’s add some extra squares and have them all spin side by side once. Note we’ve changed the `animation-timing-function` value to `ease-out`.

![Three squares animate in sync next to each other](https://thepracticaldev.s3.amazonaws.com/i/udexepm3msm2bnn8pf7j.gif)

{% codepen https://codepen.io/jh3y/pen/LYEWyMb %}

If we add a delay to each square could we create a staggered effect?

```css
div {
  animation-duration: 1s;
  animation-name: spin;
  animation-timing-function: ease-out;
}
div:nth-of-type(1) {
  animation-delay: 0s;
}
div:nth-of-type(2) {
  animation-delay: 0.5s;
}
div:nth-of-type(3) {
  animation-delay: 1s;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

```

The answer is yes! 👍

{% codepen https://codepen.io/jh3y/pen/BVLygY %}

But, if we then wanted the squares to keep spinning we would lose the staggered effect. This is because `animation-delay` is only applied once before the animation begins 👎 It does not apply to every iteration of an animation. At this point, we have two choices. We could experiment with different delays using the [Animations Inspector](https://developers.google.com/web/tools/chrome-devtools/inspect-styles/animations). Or we could try stalling the first half of the animation by delaying the spin.

```css
@keyframes spin {
  0%, 50% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
```
In fact, if we leverage CSS variables, we can create some interesting effects with delay. For example, using negative delays. This can give the effect of our animation already being in full swing at a certain point. A great use case is staggering animations without staggering elements into animated states. Move the slider in this demo to see some of the different effects we can achieve.

{% codepen https://codepen.io/jh3y/pen/qBdzbGb %}

# animation-fill-mode
Next up is `animation-fill-mode`. This one’s magic 🎩

By default, when we apply an animation to an element, it has no effect before or after it has run. `animation-fill-mode` changes that.

The values for `animation-fill-mode` that we can use;

- `none` - element retains no styling
- `forwards` - element retains animation styling
- `backwards` - element retains style from the first keyframe
- `both` - element retains styling in both directions

Let’s consider an animation where we shrink an element to half its size. The `animation-fill-mode` is set to `none`.

{% codepen https://codepen.io/jh3y/pen/jOEBmRJ %}

Without using `animation-fill-mode` the element returns to initial size at the end of the animation. But using `animation-fill-mode` means we can keep the element at half size once the animation ends 👍

```css
div {
  animation-delay: 1s;
  animation-duration: 0.5s;
  animation-fill-mode: forwards;
  animation-name: shrink;
  animation-timing-function: ease-out;
}
@keyframes shrink {
  to {
    transform: scale(0.5);
  }
}
```

{% codepen https://codepen.io/jh3y/pen/QxKKbg %}


Now a more common scenario for using `animation-fill-mode` is when showing and hiding elements. Consider a scenario where we have three elements that we want to fade in.

```css
@keyframes fadeIn {
  from {
    opacity: 0;
  }
}
```

We’d prefer a staggered effect so we give each element a different `animation-delay`.

{% codepen https://codepen.io/jh3y/pen/vYExmqW %}

But the outcome is not quite as desired because we didn’t use `animation-fill-mode` 👎 Applying `animation-fill-mode: backwards` will fix it!

{% codepen https://codepen.io/jh3y/pen/BVLLRW %}

For another demo consider this walk sign using `animation-fill-mode` 🚶

{% codepen https://codepen.io/jh3y/pen/MXjerm %}

# animation-direction

Last but not least is `animation-direction`. No surprises that this property allows you to define the direction of your animation. There are four main keywords;

- `alternate` - the direction of the animation alternates on each iteration
- `alternate-reverse` - same as `alternate` but starts in reverse
- `normal` - self-explanatory
- `reverse` - the animation is played in reverse

For example we could use `alternate` for something that opens and closes.
How about a clapper board?

{% codepen https://codepen.io/jh3y/pen/OERRaj %}

Using an `animation-iteration-count` of `2` with `animation-direction` `alternate` saves us writing separate animations.

# animation shorthand
If you’ve got this far, that’s all the `animation` properties 🎉 You know them all now 🤓 There’s now an opportunity to tidy up your animation code by using the shorthand property. That’s right, you don’t need to write out all the properties each time 😅

This

```css
div {
  animation-delay: 1s;
  animation-direction: normal;
  animation-duration: 0.5s;
  animation-fill-mode: normal;
  animation-iteration-count: infinite;
  animation-name: spin;
  animation-play-state: running;
  animation-timing-function: ease-out;
}
```

Is equivalent to this

```css
div {
  animation: spin 0.5s 1s ease-out infinite normal none running;
}
```

Sweet 🍭

```css
animation: [NAME] [DURATION] [DELAY] [TIMING-FUNCTION] [ITERATION-COUNT] [DIRECTION] [FILL-MODE] [PLAY-STATE];
```

Those properties are optional so we can use whichever combination required 👍

But that’s not all. Using the `animation` property makes it a little easier to apply many animations to an element.

Consider an element that we make come in from below and then rotate by 45 degrees.

```css
div {
  animation-delay: 0s, 0.5s;
  animation-duration: 0.5s, 0.75s;
  animation-fill-mode: forwards;
  animation-name: flyIn, rotate;
}
@keyframes flyIn {
  from {
    opacity: 0;
    transform: translateY(300%) scale(0);
  }
}
@keyframes rotate {
  to {
    transform: rotate(45deg);
  }
}
```

You can use comma-separated values for your `animation` properties. But you could also do this


```css
div {
  animation: flyIn 0.5s forwards, rotate 0.5s 0.75s forwards;
}
```

This opens up a whole plethora of opportunities 🤓

{% codepen https://codepen.io/jh3y/pen/VdKPvd %}

# That’s it for Part 2! 🎉

We’ve gone through the different `animation` properties and their behavior.

You should now be in a pretty good place with CSS animation 💪 I hope you’ll join me in [Part 3]() where we wrap up by looking at different ways of using CSS animations.

[![Link to part 3](https://thepracticaldev.s3.amazonaws.com/i/yhn46zgwfzm4z7ma9qy1.png)](https://dev.to/jh3y/a-guide-to-css-animation-part-3-3g20)

Remember, all of the demo code is available in the following CodePen collection 👍

[![Link to CodePen collection of demos](https://thepracticaldev.s3.amazonaws.com/i/jqssaberzcdexpoqwzce.png)](https://codepen.io/collection/nMpBQm/)

As always, any questions or suggestions, please feel free to leave a response or [tweet me 🐦](https://twitter.com/@jh3yy)! Be sure to connect with me on the socials! 😎