Deep Tech Point
first stop in your tech adventure

A complete guide to CSS animations (with all 8 animation subproperties explained through examples)

September 1, 2021 | CSS

CSS animations are not new. They have been around for more than 10 years. CSS animations make it possible to animate HTML elements without using JavaScript or Flash! And this is one of their main advantages. They are super easy to use – you don’t even need to know JavaScript or any other animation technique that is script-driven. The CSS animations have a relatively good performance – at least compared to those in JavaScript, because the rendering engine uses frame-skipping and other techniques to keep the performance as smooth as possible. In addition to that, since the browser controls the animation sequence, the browser is also the one that optimizes performance and efficiency. For example, when the user has several open tabs but is not viewing the tab with animation, the browser will reduce the update frequency of animations. So, yes, CSS animations are great and are in general well supported by newer browsers. However, there are performance issues. There are four things modern browsers can animate without any problems: position, scale, rotation and opacity. However, if you animate anything else, it’s at your own risk.
In this tutorial, we will go through the animation shorthand property and we will explain all 8 subproperties and their values through examples.

What are CSS animations?

CSS animations animate HTML elements – they let an element steadily transforms from one style to another. In other words – CSS animations animate transitions from one CSS style configuration to another. In essence, you can animate as many CSS properties you want, as many times as you want (there are some performance issues, but more about that later!), but you must declare some keyframes for the animation.
And these are actually the 2 main components that are an inevitable part of any CSS animation:

What are @keyframes?

Let’s clear this first and take the definition from MDN:
“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.”

So, @keyframe defines the starting and ending points of any smooth transition. It controls the happening at specific moments during the CSS animation. Let’s say an animation starts at 1 second (0% of animation) and ends at 5 seconds (100% of animation). During that time animation shorthand (or its subproperties) tell the keyframes of what and when exactly should be done with CSS animation. In other words – keyframes declare what styles the element will have at a specific time during the animation.

We specify the CSS styles inside the @keyframes rule, and then the animation at defined times steadily changes from the starting style (whatever style we declare) to the new, ending style. Obviously, we must connect the animation to an element whose styles will change.

The CSS animation syntax through two simple examples

In the example below, we will animate the <div> element and we will animate that element to change the background from “aquamarine” to “gray” in 5 seconds:

See the Pen
three colors animation percentages
by Tanja (@tanjatod)
on CodePen.

Take a look at HTML part of the code – we have to define an element – in our case <div>.
Now, take a look at CSS part of the code – we have to declare @keyframes rule – when and what will change – and in our case we used the simplified version – we have specified when the style will change by using the keywords “from” and “to”, because we have just one change, but we could also have said:

 @keyframes div-two-colors {
  0%   {background-color: aquamarine;}
  100%  {background-color: gray;}
}  

And below that, we styled our HTML element – its width and height, its background-color (after the animation ends, the div will return to the aquamarine color), we declared animation-name of the HTML element, which is connected to the @keyframes that define what and when will happen to the animation, and we defined animation-duration to last 5 seconds after which the background returns to its original color.

Now, let’s take a look at @keyframes defined with percentages. We will have animation of a div background, going from aquamarine, to gray and pink in 10 seconds, after the animation finishes, the background goes “black”:

See the Pen
three colors animation percentages
by Tanja (@tanjatod)
on CodePen.

And now, let’s take a look at an animation that has applied changes in two styles: color and position of the <div> element – it will go from aquamarine on the left to gray on the right, and then return to be pink on the left. When the animation ends, the <div> element will change its color to black. Remember to include position: relative; when styling the div, otherwise, the position won’t change. And obviously, since our div has 200px x 200 px dimensions, the change of the position have to be larger in length than the div’s dimensions.

See the Pen
by Tanja (@tanjatod)
on CodePen.

It’s majesty – the animation shorthand

If you have followed through with the examples above, you’ve already learned a lot about CSS animations. Still, there is so much more to learn. In this chapter, we will teach you in detail about animation shorthand and its 8 subproperties. You will also learn how to manipulate these subproperties by applying different values. These are the 8 subproperties of animation property:

1. animation-name subproperty

There’s not that much to this you haven’t learned already. This subproperty declares the names of one or more @keyframes at-rule that describe the animation(s) to apply to the element.
Take a look at the CSS pencodes in this article – animation-name is listed with the @keyframes that declare what and when the change of style will happen, and again below when defining the style of an html element. This way, by using the animation-name we actually connect @keyframes with a style of html element.

2. animation-duration to define animation length

animation-duration subproperty defines the length of time it takes for an animation to finish one animation cycle. Super simple and self-explanatory, right? You’ve already used this property in previous examples, as a matter of fact, you have to declare this property if you want an animation to run. The default value is 0s, and if you declare zero seconds; or if you do not declare that property at all, the animation will not show. You can declare animation-duration with seconds (s) or milliseconds (ms), and the value you declare must be positive.

Multiple animation property and animation-duration

If you are working with multiple animation property values, you must separate values with commas. The animation-duration will be assigned to animations specified in the animation-name property in different ways depending on how many there are. It is best if we take a look at that with the help of two simple examples.

animation-name: animation1, animation2, animation3;
animation-duration: 1s, 2s, 3s;

The code above says: run animation1 1 second, run animation2 for 2 seconds, and animation3 for 3 seconds. Makes sense.

But what about this code below?

animation-name: animation1, animation2, animation3;
animation-duration: 1s, 2s;

No, animation3 will not last 0 seconds! Animation3 will last 1s! The browser will read this like so:
animation1 lasts 1s, animation2 lasts 2 seconds. And now what? We’ve got to the end of the available duration values, so we start at the beginning again, meaning the animation3 gets 1s duration.

The code below says all three animations have a duration of 1 second:

animation-name: animation1, animation2, animation3;
animation-duration: 1s;

3. animation-timing-function to declare the speed curve of the animation

Animation always follows a certain speed curve of the animation, which as the name suggests defines how quickly or slowly will the animation proceed during each animation cycle. So, the animation-timing-function subproperty declares the speed curve of animation – whether the animation will start slowly, progress faster, whether it will have the same speed from beginning to the end of the animation, and so on. Below you will find a list of possible values of the animation-timing-function subproperty with their descriptions. The first block of possible values is based on the cubic-bezier function:

See the Pen
by Tanja (@tanjatod)
on CodePen.

The second block of possible values for animation-timing-function is based on steps (animation stops) and jump terms. Animation has a certain number of stops (steps) during the transition and each stop is displayed for an equal amount of time. However, how exactly these stops are controlled, depends on the jumpterm that you use. Below you will find a list of possible steps combining different jumpterms with explanations for each:

Let’s take a peek at how this looks on animations:

See the Pen
animations-steps-jumpterms
by Tanja (@tanjatod)
on CodePen.

Multiple animation property and animation-timing-function

As you already know, if you are working with multiple animation property values, you must separate values with commas. The animation-timing-function will be assigned to animations specified in the animation-name property in different ways depending on how many there are, basically, it follows the same rule (and examples) we explained in the animation-duration property.

The code below says the following: animation1 applies ease animation-timing-function, animation2 linear, and animation3 is directed by jump-none animation-timing-function:

animation-name: animation1, animation2, animation3;
animation-timing-function: ease, linear, jump-none;

But what happens here?

animation-name: animation1, animation2, animation3;
animation-timing-function: ease, linear;

animation1 applies ease animation-timing-function, animation2 linear, and animation3 is reads from the beginning again – it uses ease animation-timing-function.

And here?

animation-name: animation1, animation2, animation3;
animation-timing-function: ease; 

All three animations apply ease animation-timing-function.

4. animation-delay subproperty to delay the animation start

animation-delay subproperty controls the delay of the animation start – the time between the element is being loaded and the start of the animation sequence. In the following example, we applied a 5-second delay, which means a browser will load animation and then wait 5 seconds before the animation will start:

See the Pen
animation-delay
by Tanja (@tanjatod)
on CodePen.

One more important thing to bring out here – with animation-delay negative values are also allowed. So, when using negative values, the animation will start as if it had already been playing for X seconds. We will use the example from above but will declare -5s, so the animation will start as if it had already been playing for 5 seconds. Let’s see what happens in an example:

See the Pen
animation-negative-delay
by Tanja (@tanjatod)
on CodePen.

5. animation-iteration-count controls how many times the animation should be performed

This property dictates how many times the animation will repeat before stopping. 1 is the default value, so the animation repeats only once. You can also define a non-integer value, such as 1.5, which means the animation will play one full cycle, return to the beginning (if the animation-direction is the default), and play the first half of the animation again. You cannot declare negative values. You can also declare <infinite> value, which means the animation will repeat forever.

Let’s see how this looks in practice:

See the Pen
showcase-animation-iteration-count
by Tanja (@tanjatod)
on CodePen.

Multiple animation property and animation-iteration-count

If multiple values are specified, each time the animation is played the next value in the list is used, and after the last value in the animatiton-iteration-count property list is used, the browser will go back to reading the first value in the list. Let’s take a look at the examples.

The code below says the following: animation1 repeats once, animation2 2.5 times, and animation3 will repeat forever:

animation-name: animation1, animation2, animation3;
animation-iteration-count: 1, 2.5, infinitive;

But what happens here?

animation-name: animation1, animation2, animation3;
animation-iteration-count: 1, 2.5;

animation1 repeats once, animation2 2.5 times, and animation3 reads from the beginning again of property values- it repeats once.

And here?

animation-name: animation1, animation2, animation3;
animation-iteration-count: 2.5; 

All three animations will repeat 2.5 times.

6. animation-direction to set the direction of the animation after the cycle

The animation-direction subproperty dictates whether an animation should be played forwards, backwards, or whether it should be played in alternate cycles back and forth on each run between playing sequence forward and backward. Below you will find a list of possible values with explanations:

Let’s have a peak at how this looks in practice:

See the Pen
showcase-animation-direction
by Tanja (@tanjatod)
on CodePen.

Multiple animation property and animation-direction

As you already know, if you are working with multiple animation property values, you must separate values with commas. The animation-direction will be assigned to animations specified in the animation-name property in different ways depending on how many there are, basically, it follows the same rule (and examples) we explained in the animation-duration and animation-timing-functionproperty.

The code below says the following: animation1 applies ease animation-direction, animation2 reverse, and animation3 is directed by alternate animation-direction property:

animation-name: animation1, animation2, animation3;
animation-direction: normal, reverse, alternate;

But what happens here?

animation-name: animation1, animation2, animation3;
animation-direction: normal, reverse;

animation1 applies normal animation-direction, animation2 reverse, and animation3 is reads from the beginning again – it uses normal animation-direction.

And here?

animation-name: animation1, animation2, animation3;
animation-direction: normal; 

All three animations apply normal animation-direction.

7. animation-fill-mode sets which values are applied before and/or after the animation

animation-fill-mode controls what happens before an animation starts and after it ends. This property also tells the browser if the animation’s styles should be applied outside of the animation, too. In general, CSS animations do not affect the element before (or after) the first (last) keyframe is played, however, the animation-fill-mode property can override this behavior. Let’s take a look at a list of possible values with explanations:

So, the animation-fill-mode can set the last state of the animation to remain on screen, or you can set it to switch back to before when the animation began. So, this property defines what values are applied by an animation outside the time it is executing. More specifically, it defines what styles are applied to the element during the animation delay time, and after the animation has finished execution.
However, you should keep in mind that this property is closely connected to animation-direction, because its definition is dependent on the first or last keyframe and also animation-iteration-count because of the even or odd number of iterations.

See the Pen
by Tanja (@tanjatod)
on CodePen.

This showcase presents an example where both texts have the same animation – the text grows bigger. But the one that stays big also contains animation-fill-mode property with a value <forwards> so the last keyframe from the animation persists after it has finished execution – the text stays big. This example also presents how nicely pseudo-classes can be combined with animation.

See the Pen
by Tanja (@tanjatod)
on CodePen.

Multiple animation property and animation-fill-mode

If multiple values are specified, each time the animation is played the next value in the list is used, and after the last value in the animatiton-fill-mode property list is used, the browser will go back to reading the first value in the list. Let’s take a look at the examples.

The code below says the following: animation1 does not apply any styles, animation2 applies the last keyframe, and animation3 will apply the first keyframe:

animation-name: animation1, animation2, animation3;
animation-fill-mode: none, forwards, backwards;

But what happens here?

animation-name: animation1, animation2, animation3;
animation-fill-mode: forwards, backwards;

animation1 applies the last keyframe after animation ends, animation2 applies the first one, and animation3 again applies the last keyframe after animation ends.

And here?

animation-name: animation1, animation2, animation3;
animation-fill-mode: forwards; 

All three animations will apply the last keyframe after the animation ends if animation-direction and animation-iteration-count are set to default.

8. animation-play-state property pauses or plays the animation

This property sets whether an animation is being played or paused. So, there are two values to this property:

There is one more thing worth mentioning here. When a paused animation is resumed, the animation will start from where it left off at the time it was paused, it will not start over from the beginning of the animation sequence.

So, how to use the shorthand animation property?

Let’s go through and read the shorthand animation property through an example. Let’s say this:

div {
animation: happy 10s ease-in-out -2s infinite reverse backwards running;
}

We’ve put all 8 subproperties in one line, but we could replace them with the following:

div {
animation-name: happy
animation-duration: 10s
animation-timing-function: ease-in-out
animation-delay: -2s
animation-iteration-count: infinite
animation-direction: reverse
animation-fill-mode: backwards
animation-play-state: running
}

How to set multiple animation property values?

Unfortunately, in this case, we cannot use animation shorthand, but we have to use the CSS animation longhand values. This is the only way we can apply multiple values and we have to separate them by commas. This way we can apply multiple animations in a single rule, and set different values for different properties for separate animations.

We’ve already worked through a few examples in previous chapters of this tutorial, but let’s aggregate this knowledge here:

div {
animation-name: animation1, animation2, animation3;
animation-duration: 3s;
animation-timing-function: ease-in;
animation-iteration-count: 1, 2;
delay: -2s, 0s, 0s; 
animation-fill-mode: backwards; 
}

OK, let’s read this.

Animation1 (animation-name) will last 3 seconds (animation-duration), it will apply ease-in acceleration curves (animation-timing-function), it will repeat once (animation-iteration-count), it will have negative 2s delay, which means the animation will start as if it had already been playing for 2 seconds, and the animation-fill-mode it will apply will be backwards – in this case, it means that after the animation ends it will apply the first relevant keyframe from the animation (because we didn’t explicitly declare the animation-direction, so that property is the default, t.i <normal>.

Animation2 will last 3 seconds, it will apply ease-in speed curve, the animation will repeat two times, it won’t have any delay (0s), and it will take the style from the first keyframe of the animation (backwards). Notice this – we said 0s for animation-delay because we don’t want any delay. If we wouldn’t declare that, the animation2 would take the delay that has been previously defined (-2s).

Animation3 lasts 3 seconds, it will apply ease-in speed curve. Now watch this – the animation will repeat only once (!) – browser got to the end of available values (1 and 2) and started reading from the beginning, so 1 repetition. The animation-delay is 0 seconds again, and the fill-mode is backwards.