CSS animations are made up of two basic building blocks.
Keyframes
define the stages and styles of the animation.Animation Properties
assign the @keyframes to a specific CSS element and define how it is animated.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 propertiesKeyframes 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); } }
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 -
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.
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; }
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>
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 ease
which 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 -
The animation-iteration-count: specifies the number of times that the animation will play. The possible values are:
infinite
- the animation repeats forever.@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.
The animation-direction: property specifies whether the animation should play forward, reverse, or in alternate cycles.
The possible values are:
normal
- The animation plays forward. On each cycle the animation resets to the beginning state (0%) and plays forward again (to 100%). This is the default value.reverse
- The animation plays backwards. On each cycle the animation resets to the end state (100%) and plays backwards (to 0%).alternate
- The animation reverses direction every cycle. On each odd cycle, the animation plays forward (0% to 100%). On each even cycle, the animation plays backwards (100% to 0%).alternate-reverse
- The animation reverses direction every cycle. On each odd cycle, the animation plays in reverse (100% to 0%). On each even cycle, the animation plays forward (0% or 100%)..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
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.
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
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];
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; }
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; } }
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);} }