CSS Animation
CSS animations make it possible to animate transitions from one CSS style configuration to another. Animations consist of two components, a style describing the CSS animation and a set of keyframes that indicate the start and end states of the animation’s style, as well as possible intermediate waypoints.
Keyframes
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.
Animation Properties
The purpose the animation property is not to describe the appearance of the animation, that is the job of the @keyframes
CSS at-rule, but to describe how those rules should be applied on the target elements.
The following properties can be used:
animation-name
The animation-name
property specifies the name of the @keyframes
at-rule describing the animation’s keyframes.
animation-duration
The animation-duration
property configures the length of time that an animation should take to complete one cycle.
animation-timing-function
The animation-timing-function
property configures the timing of the animation; that is, how the animation transitions through keyframes, by establishing acceleration curves.
animation-delay
The animation-delay
property sets a delay between the time the element is loaded and the beginning of the animation sequence.
animation-iteration-count
The animation-iteration-count
property defined the number of times the animation should repeat; you can specify infinite
to repeat the animation indefinitely.
animation-direction
The [animation-direction](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-direction) property set the direction in which animation will run through the keyframes of the
@keyframes` at-rule.
animation-fill-mode
The animation-fill-mode
property defines what CSS values are applied to the element before and after the animation has executed.
animation-play-state
The animation-play-state
determines whether the animation is running
or paused
Creating CSS Animations
A simple animation
Generally, the first step to creating a CSS animation is to create the keyframes. We need to create two or more keyframes to define a start and end state. At a minimum, we specify a name for our animation following the @keyframes
keyword then define our start and end points.
In the example below, we use the from
and to
keywords to declare the start and end states.
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
Once keyframes are created, we can apply it to an element using the animation-properties. The animation-name
and animation-duration
are the only required animation-properties.
.rotate {
animation-name: rotate;
animation-duration: 1s;
}
A jumping box
The famous book The Illusion of Life gave us the 12 basic principles of animation, and while the book was derived these principles from the work of the Disney animator, they can still be applied to the CSS animations. However, to create believable animations you have to understand how to use the different animation properties effectively.
To create the effects of squishing and squashing often requires using the transform property in subtle ways. In the example below, the box will jump, but no effort was made to make it realistic.
@keyframes jump {
50% {
transform: translate(0, -200px);
}
}
While animation was achieved, it was not very realistic. The following version using the transform scale()
function was used to make the animation more appealing.
@keyframes jump {
10%,
25% {
transform: scale(1.3, 0.7);
}
50% {
transform: scale(0.5, 2) translate(0, -200px);
}
60% {
transform: scale(1, 1) translate(0, 0);
}
75% {
transform: scale(1.3, 0.7) translate(0, 0);
}
85% {
transform: scale(1, 1) translate(0, 0);
}
}
A pendulum
For this next example, we will simulate a pendulum swinging back and forth. This example will customizing the animation-direction
, animation-timing-function
and the animation-fill-mode
properties.
The animation-direction
property allows us to set what direction through the keyframes we want the animation to go, normal
(0% to 100%), reverse
(100% to 0%), or alternate
, which alternate between normal
or reverse
between each animation cycle.
The animation-fill-mode
can be confusing for beginners, but all it does is determine which styles should be set before and after an animation is executed. For example, if animation-fill-mode
is set to backwards
the first keyframe will be applied to the element before the animation begins, and if the animation-fill-mode
is set to forwards
the last keyframe will be applied to the element after the animation has ended.
NOTE
The value forwards
will have no effect on an animation with an iteration-count
of infinite
, because the animation never ends.
In this first example, we are not customizing the animation-direction
, animation-fill-mode
or the animation-timing-function
.
NOTE
To create the pendulum animation, we adjust the transform-origin
property to move the transformation point 100px above the block.
@keyframes swing {
/* These styles will be applied throughout the animation */
0%,
100% {
border-radius: 50%;
transform-origin: 0 -100px;
}
0% {
transform: rotate(77deg);
}
100% {
transform: rotate(-45deg);
}
}
.swing {
animation-name: swing;
animation-duration: 2s;
animation-delay: 2s;
animation-iteration-count: infinite;
}
Now, lets add animation-fill-mode
and animation-direction
.
@keyframes swing {
/* These styles will be applied throughout the animation */
0%,
100% {
border-radius: 50%;
transform-origin: 0 -100px;
}
0% {
transform: rotate(77deg);
}
100% {
transform: rotate(-45deg);
}
}
.swing {
animation-name: swing;
animation-duration: 2s;
animation-delay: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: backwards;
}
The animation looks better, but the timing is off.
Timing is so important for creating believable animations. If the timing is not right the whole animation will look... off. We can control the timing of an animation with the animation-timing-function
property. This property sets the speed curve of the animation, which is how fast through the keyframes the animation is going at any time during the animation cycle. For example, Is the animation simulating going down a hill, starting off slow and end moving fast (ease-in
) or is it coming to a stop from high speed (ease-out
)?
CSS includes several pre-built speed curves which can be accessed using the following keywords: ease
, ease-in
, ease-out
, ease-in-out
, and linear
. While these pre-built options are convenient, they can also be limiting. That is why there is also the cubic-bezier()
function, which will allow you to create your own speed curve. There are even cubic bezier generators, like https://cubic-bezier.com/, which can help you create just the right timing.
Lets customize the timing function of our pendulum to make it flow more naturally. Fortunately, we can use one of the pre-built options ease-in-out
.
@keyframes swing {
/* These styles will be applied throughout the animation */
0%,
100% {
border-radius: 50%;
transform-origin: 0 -100px;
}
0% {
transform: rotate(77deg);
}
100% {
transform: rotate(-45deg);
}
}
.swing {
animation-name: swing;
animation-duration: 2s;
animation-delay: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: backwards;
animation-timing-function: ease-in-out;
}
A wave
In this final example, we will learn how an animation added to multiple elements can create a totally new effect, and we will accomplish this by using the animation-delay
property.
In this first example, we have applied a simple animation to multiple elements.
@keyframes wave {
0%,
50%,
100% {
background-color: orange;
transform: scale(1);
}
25% {
background-color: yellow;
transform: scale(1, 2);
}
75% {
background-color: red;
transform: scale(1, 0.5);
}
}
.wave {
animation-name: wave;
animation-duration: 2s;
animation-iteration-count: infinite;
}
Now, lets add a delay to animation, increasing the delay time for each element.
@keyframes wave {
0%,
50%,
100% {
background-color: orange;
transform: scale(1);
}
25% {
background-color: yellow;
transform: scale(1, 2);
}
75% {
background-color: red;
transform: scale(1, 0.5);
}
}
.wave {
animation-name: wave;
animation-duration: 2s;
animation-iteration-count: infinite;
}
.wave:nth-child(1) {
animation-delay: 0.2s;
}
.wave:nth-child(2) {
animation-delay: 0.4s;
}
.wave:nth-child(3) {
animation-delay: 0.6s;
}
.wave:nth-child(4) {
animation-delay: 0.8s;
}
.wave:nth-child(5) {
animation-delay: 1s;
}
Once again, our timing is off. So, let us go back and add different timing function, linear
.
@keyframes wave {
0%,
50%,
100% {
background-color: orange;
transform: scale(1);
}
25% {
background-color: yellow;
transform: scale(1, 2);
}
75% {
background-color: red;
transform: scale(1, 0.5);
}
}
.wave {
animation-name: wave;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.wave:nth-child(1) {
animation-delay: 0.2s;
}
.wave:nth-child(2) {
animation-delay: 0.4s;
}
.wave:nth-child(3) {
animation-delay: 0.6s;
}
.wave:nth-child(4) {
animation-delay: 0.8s;
}
.wave:nth-child(5) {
animation-delay: 1s;
}
Further Review
Review the following material and be sure to download the lesson file to begin exploring animations.
References
- Animations - CSS Reference
- animation - CSS: Cascading Style Sheets | MDN
- animation-name - CSS: Cascading Style Sheets | MDN
- animation-duration - CSS: Cascading Style Sheets | MDN
- animation-timing-function - CSS: Cascading Style Sheets | MDN
- animation-delay - CSS: Cascading Style Sheets | MDN
- animation-iteration-count - CSS: Cascading Style Sheets | MDN
- animation-direction - CSS: Cascading Style Sheets | MDN
- animation-fill-mode - CSS: Cascading Style Sheets | MDN
- animation-play-state - CSS: Cascading Style Sheets | MDN
- W3C - CSS Animations Level 1
Reach Ahead
- CSS: Animation - Welcome | LinkedIn Learning, formerly Lynda.com
- Beyond Flash: Creating animations for the modern web | LinkedIn Learning, formerly Lynda.com
This YouTube video was created by Steve Griffith.