Animation

CSS animations are made up of two basic building blocks.

Animatable Properties

Some CSS properties are animatable, meaning that they can be used in animations and transitions.

Animatable properties can change gradually from one value to another, like size, numbers, percentage and color.

There are lots of properties available in CSS. Not all the properties can be animatable. If a property is animatable, it means we can animate the property. Say, color is animatable property. We can animate the color property of an element, it means we can change the color of an element from red to blue or blue to red etc.

Click here to know if an property is animatable, this link contains all the animatable properteis -

Mozilla - CSS animated properties

Keyframes

Keyframes are the foundation of CSS animations. They define what the animation looks like at each stage of the animation timeline. Each @keyframes is composed of:

Let’s take a look at a simple @keyframes I’ve named “bounceIn”. This @keyframes has three stages. At the first stage (0%), the element is at opacity 0 and scaled down to 10 percent of its default size, using CSS transform scale. At the second stage (60%) the element fades in to full opacity and grows to 120 percent of its default size. At the final stage (100%), it scales down slightly and returns to its default size.

The @keyframes are added to your main CSS file.

@keyframes bounceIn {
  0% {
    transform: scale(0.1);
    opacity: 0;
  }
  60% {
    transform: scale(1.2);
    opacity: 1;
  }
  100% {
    transform: scale(1);
  }
}

Animation Properties

Once the @keyframes are defined, the animation properties must be added in order for your animation to function.

Animation properties do two things:

The animation properties are added to the CSS selectors (or elements) that you want to animate. You must add the following two animation properties for the animation to take effect:

Continuing with the above bounceIn example, we’ll add animation-name and animation-duration to the div that we want to animate.

div {
  animation-duration: 2s;
  animation-name: bounceIn;
}

Shorthand syntax:

div.bounceIn{
  animation: bounceIn 2s;
}

By adding both the @keyframes and the animation properties, we have a simple animation!

Reload the page again to see the animation again. Now you know how to use animataion. Let's learn everything in details -

animation-name

This property is used to specify the name of the animation that we want to animate on the element. This name is the keyframe name that defines the animation. This property is required in order for the animation to work.

.example{
	animation-name : slideUp;
}	

This property can take none keyword as the value. It means that the element won't animate.

animation-duration

This property specifies the duration of the animation for how long the animation will continue. You can provide the value either in second or milliseconds. This is a required property and without this property the animation won't work.

.example{
	animation-duration : 5s;
}
.example{
	animation-duration: 1200ms;
}

animation-delay

This property is used to specify the delay duration for how long it should wait before the animation begins.

When you activate the animation, if there's a animation-delay, then it will wait for that specified amount, otherwise the animation will start instantlyl.

.example{
	animation-delay : 200ms;
}

If you don't provide this property, the default value is 0, it means the animation will start immediately after activating the animation.

Here is an example. Refresh the page to play the animation -

.ball{
	height: 50px;
	width: 50px;
	border-radius: 50%;
}
.animateBall{
	animation-name: moveRight;
	animation-duration: 2s;
}
@keyframes moveRight{
	0%{transform: translate(0px);}
	50%{transform: translate(700px);}
	100%{transform: translate(0px);}
}
<div class="box" id="animateBall">
	<div class="ball animateBall" style="background: crimson; animation-delay: 0;"></div>
	<div class="ball animateBall" style="background: yellow; animation-delay: 100ms;"></div>
	<div class="ball animateBall" style="background: red; animation-delay: 200ms;"></div>
	<div class="ball animateBall" style="background: black; animation-delay: 300ms;"></div>
	<div class="ball animateBall" style="background: blue; animation-delay: 400ms;"></div>
	<div class="ball animateBall" style="background: pink; animation-delay: 500ms;"></div>
</div>

animation-timing-function

You have already learnt about transition-timing-function. animation-timing-function is the same thing. You can use the same value. The default value is easewhich starts out slow, speeds up, then slows down.

.example{
	animation-timing-function: ease-in-out;
}

Here is an example. In the following example, we are using the above example, instead we have removed all the animation-delay property and substituted with animation-timing-function property. See the difference for each keyword -

Animation-iteration-count

The animation-iteration-count: specifies the number of times that the animation will play. The possible values are:

	@keyframes rotate{
	0%{transform: rotate(0deg);}
	50%{transform: rotate(360deg);}
	100%{transform: rotate(0deg);}
}
.rotateBoxy{
	width: 100px; 
	height: 100px; 
	background: crimson; 
	border-top-left-radius: 50%; 
	border-bottom-right-radius: 50%; 
	animation-name: rotate;
	animation-duration: 2s;
	animation-iteration-count: infinite;
}
<div class="box" style="display: flex; justify-content: center; align-items: center;">
	<div class="rotateBoxy"></div>
</div>

The example above will play the animation forever.

animation-direction

The animation-direction: property specifies whether the animation should play forward, reverse, or in alternate cycles.

The possible values are:

.ballx{
	height: 40px;
	width: 40px;
	background: crimson;
	border-radius: 50%;
	margin: 20px;
	animation-name: moveBallX;
	animation-duration: 3s;
}
@keyframes moveBallX{
	0%{transform: translate(0px);}
	25%{transform: translate(200px);}
	75%{transform: translate(-200px);}
	100%{transform: translate(0);}
}
<div class="box" style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
	<div class="ballx" style="animation-direction: normal;"></div>
	<div class="ballx" style="animation-direction: reverse;"></div>
	<div class="ballx" style="animation-direction: alternate;"></div>
	<div class="ballx" style="animation-direction: alternate-reverse;"></div>
</div>

Well, you cannot make much difference between normal and alternate if you place the animation only once or too few times to notice. Let's look at the following example we have animation-iteration-count to 10 -

animation-fill-mode

animation-fill-mode specifies if the animation styles are visible before or after the animation plays. This property is a little confusing, but once understood it is very useful.

By default, the animation will not effect the styles of the element before the animation begins (if there is an animation-delay) or after the animation is finished. The animation-fill-mode property can override this behavior with the following possible values:

Here is an example -

@keyframes enlarge{
	from{transform: scale(1);}
	to{transform: scale(2);}
}
.enlargeBox{
	animation-name: enlarge;
	animation-duration: 2s;
	height: 50px;
	width: 50px;
	background: crimson;
	border-radius: 50%;
	margin: 30px;
}
.backwardFillMode{
	animation-fill-mode: backwards;
}
.forwardFillMode{
	animation-fill-mode: forwards;
}
.bothFillMode{
	animation-fill-mode: both;
}
<div class="box" style="height: 150px; display: flex; justify-content: center; align-items: center;">
	<div style="display: flex; justify-content: center; align-items: center;">
		<div class="enlargeBox"></div>
		<div class="enlargeBox backwardFillMode"></div>
		<div class="enlargeBox forwardFillMode"></div>
		<div class="enlargeBox bothFillMode"></div>
	</div>
</div>

Refresh the page to play the animation again. As you can see, the first two ball returned back to the previous state it was before the animation. After the animation they are reset again with their original property.

However the last two ball didn't returned back to the previous state, it catches the final state of the annimation and applies to the element after the animation.

animation-play-state

The animation-play-state: specifies whether the animation is playing or paused. Resuming a paused animation starts the animation where it was left off.

The possible values are:

Here is an demo -

.leave{
	height: 50px;
	width: 50px;
	border-top-left-radius: 50%;
	border-bottom-right-radius: 50%;
	height: 100px;
	width: 100px;
	background: crimson;
	animation-name: rotating;
	animation-duration: 2s;
	animation-iteration-count: infinite;
}
.leave:hover{
	animation-play-state: paused;
}
@keyframes rotating{
	0%{transform: rotate(0deg);}
	50%{transform: rotate(3600deg);}
	100%{transform: rotate(0deg);}
}
<div class="box" style="display: flex; justify-content: center; align-items: center; height: 150px;">
	<div class="leave"></div>
</div>

In the above example, we are pausing the animation on mouse hover on the element. The following example plays the aninmation on mouse hover -

animation

animation is the shorthand property of all the above 6 properties.

Following is the syntax -

animation: [animation-name] [animation-duration] [animation-timing-function]
[animation-delay] [animation-iteration-count] [animation-direction]
[animation-fill-mode] [animation-play-state];

Add Multiple Animation

To add multiple animations to a selector, you simply separate the values with a comma. Here’s an example:

.div {
  animation: slideIn 2s, rotate 1.75s;
}
.element {
  animation: 
    pulse 3s ease infinite alternate, 
    nudge 5s linear infinite alternate;
}

Multiple steps

If an animation has the same starting and ending properties, it's useful to comma-separate the 0% and 100% values inside @keyframes:

@keyframes pulse {
  0%, 100% {
    background-color: yellow;
  }
  50% {
    background-color: red;
  }
}

from-to

Instead of using percentage you can use the keyword from and to. from means 0% and to means 100%.

@keyframes keyFromTo{
	from{transform: scale(2);}
	to{transform: scale(3);}
}

You can also combine percentage with keyword like this -

@keyframes keyFromTo{
	from{transform: scale(2);}
	50%{background: yellow;}
	to{transform: scale(3);}
}