# Animations
- Just like transitions, animations allow you to gradually or smoothly change one or more properties from one style to another
- Where transitions can only be triggered on state changes (like
:hover
,:active
,:focus
,:checked
, ...), animations can be used in a wider context - Every animation consists of two parts:
- an animation style that describes the duration, timing, direction, ... of the animation
- a set of keyframes with a start, end and intermediate points that describe the changes itself
- Take a look at one of the oldest animations: the Spiderman example from 2010
# @keyframes
- The @keyframes at-rule contains all the different keyframes (states) of the animation
- Each keyframe contains the properties of an element at a specific moment in time
- Because the actual duration of the animation is determined by the animation properties, the different keyframe selectors (stops or breaking points) within @keyframes are written in percentages
0%
(orfrom
): start of the animation100%
(orto
): end of the animation50%
: in the middle of the animation- ...
- You can omit the
0%
keyframe if the start of the animation contains no values
# Quick example
- Let us discuss a simple animation (before we dive into the details of the animation style)
- The animation on the
p
tag uses thechangeColor
at-keyframe rule - The animation runs in 4 seconds (
4s
) and has aninfinite
loop
- The animation on the
- Result: the background color of the
p
tag changes in4s
fromorange
toskyblue
and then starts over again
p {
...
animation: changeColor 4s infinite;
}
@keyframes changeColor {
0% {
background-color: orange;
}
100% {
background-color: skyblue;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# Exercises
- Change
0%
tofrom
and100%
toto
: nothing changes
@keyframes changeColor {
from {
background-color: orange;
}
to {
background-color: skyblue;
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- Add a new keyframe at
50%
to change the in-betweenbackground-color
togreenyellow
@keyframes changeColor {
from {
background-color: orange;
}
50% {
background-color: greenyellow;
}
to {
background-color: skyblue;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- Add a pause of two seconds in the middle of the animation where the
background-color
staysgreenyellow
@keyframes changeColor {
from {
background-color: orange;
}
25%, 75% {
background-color: greenyellow;
}
to {
background-color: skyblue;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- Move
background-color: orange;
to thep
tag and delete thefrom
keyframe
p {
...
animation: changeColor 4s infinite;
background-color: orange;
}
@keyframes changeColor {
25%, 75% {
background-color: greenyellow;
}
to {
background-color: skyblue;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# Animation properties
- The animation properties are:
EMMET instruction | result | default | description |
---|---|---|---|
animn + TAB | animation-name: ; | the names of one or more @keyframes at-rules | |
animdur + TAB | animation-duration: ; | 0 | duration of the animation in seconds (s ) or milliseconds (ms ) |
animdel + TAB | animation-delay: ; | 0 | delay (s orms ) before the animation starts |
animtf + TAB | animation-timing-function: ; | ease | speed curve of the animation effect |
animic + TAB | animation-iteration-count: ; | 1 | number of times the animation plays |
animdir + TAB | animation-direction: ; | normal | direction the animation plays |
animfm + TAB | animation-fill-mode: ; | none | sets how the animation applies styles before and/or after its execution |
animps + TAB | animation-play-state: ; | running | sets whether the animation is running or paused |
anim + TAB | animation: ; | shorthand for all the above properties | |
anim- + TAB | animation: ; | shorthand for all the above properties but this time with hints |
REMARKS
animation
shorthand:- It is good practice (not required) to place the
amimation-name
always first - When using the
animation-duration
AND theanimation-delay
, theanimation-duration
ALWAYS comes first!
- It is good practice (not required) to place the
animation-duration
is comparable (does exactly the same for animations) totransition-duration
animation-timing-function
is comparable totransition-timing-function
animation-delay
- Comparable to
transition-delay
- In combination with an infinite loop, the
transition-delay
is the time before the animation starts and not a delay inside each loop!
- Comparable to
# animation-name
- Sets the name of the
@keyframes
at-rule(s) to be applied to a specific element - You can animate an element with two or more
@keyframes
at-rules by separating the names with a comma - For example:
div {
animation: animation1 1s, animation2 2s infinite;
}
1
2
3
2
3
# animation-iteration-count
- The
animation-iteration-count
property defines how many times the animation repeats itself- The possible values are positive numbers (also
.5
for half an animation) orinfinite
- The default value is
1
- The possible values are positive numbers (also
- In the example below:
- All balls use the same at-keyframes rule
- The first ball rolls only once, the second ball rolls two times and the last ball rolls infinitely
(TIP: Put areturn
inside the HTML part of the embedded CodePen to reload the page)
div:first-child {
animation: roll 2s;
}
div:nth-child(2) {
animation: roll 2s 2;
}
div:nth-child(3) {
animation: roll 2s infinite;
}
@keyframes roll {
to { transform: translateX(300px) rotate(360deg); }
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# animation-direction
- Possible values for
animation-direction
are:normal
: animation runs from0%
to100%
reverse
: animation runs from100%
to0%
alternate
: animation runs from0%
to100%
and back to0%
alternate-reverse
: animation runs from100%
to0%
and back to100%
div:first-child {
animation: roll 2s infinite; /* default direction: normal */
}
div:nth-child(2) {
animation: roll 2s infinite reverse;
}
div:nth-child(3) {
animation: roll 2s infinite alternate;
}
div:nth-child(4) {
animation: roll 2s infinite alternate-reverse;
}
@keyframes roll {
to { transform: translateX(300px) rotate(360deg); }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# animation-fill-mode
- The
animation-fill-mode
sets which values are applied BEFORE the animation starts and/or AFTER the animation is ended - To demonstrate this behavior, we start with a
black
box of100px
wide (the default values)
div {
background-color: black;
color: whitesmoke;
width: 100px;
padding: .5rem;
margin-bottom: .5rem;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- At the start of the animation, the box is
50%
wide and red - At the end of the animation, the box is
100%
wide and blue
@keyframes color {
from {
width: 50%;
background-color: firebrick;
}
to {
width: 100%;
background-color: dodgerblue;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- To make all possible values for
animate-fill-mode
visible, the animations start with a delay of 2 seconds when you hover thediv
tags
fill-mode | BEFORE animation starts | AFTER animation ends |
---|---|---|
none | starts with default value (black , 100px ) | goes back to the default value (black , 100px ) |
forwards | starts with default value (black , 100px ) | stays at the last keyframe (dodgerblue , 100% ) |
backwards | starts with the first keyframe (firebrick , 50% ) | goes back to the default value (black , 100px ) |
both | starts with the first keyframe (firebrick , 50% ) | stays at the last keyframe (dodgerblue , 100% ) |
- Now, hover a
div
tag and don't move your mouse until the animation ends!
# animation-play-state
- The
animation-play-state
property sets whether an animation isrunning
(default) orpaused
- In the example below:
- All circles running by default
- As long as you are hovering a
div
tag, theanimation-play-state
is set topaused
div {
...
animation: rotate 1s linear infinite; /* default animation-play-state is running */
}
div:hover {
animation-play-state: paused;
}
@keyframes rotate {
from {
background-color: coral;
}
50% {
background-color: greenyellow;
}
to {
background-color: coral;
transform: rotate(360deg);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Examples
# Animated block
- In this example, the animation of the
span
tag starts after 1.5 seconds. The animation lasts 2 seconds and thespan
goes forth and back infinitely withanimation-timing-function: ease-in-out
. Notice the use ofanimation-fill-mode:both
(orbackwards
) to start the animation correctly. - The keyframes differ in three ways:
- The
span
tag moves from left to right - Its shape changes from a circle to a rectangle
- The color changes from
red
overorange
,yellow
andgreen
toblue
- The
REMARKS
- The animation is not very responsive as the animation always ends at
300px
(even on very small or very large screens) - You can use some mathematics to animate over the full
width
of the viewport- The
span
tag starts at1rem
from the left - When we translate with
100vw
in the last keyframe, it goes1rem
outside the viewport - The
span
tag itself is3rem
wide - To stop the animation
1rem
before the right side, we have to move it1rem + 3rem + 1rem
=5rem
back
- The
- Change the
transform
property at the100%
keyframe:- from:
translateX(300px)
- to:
translateX(100vw) translateX(-5rem)
(Yes, the browser does the calculation100vw - 5rem
for two or more identical methods!)
- from:
- It can be even shorter because you can use the
calc()
method of CSS:translateX(calc(100vw - 5rem))
# Exercises
- Remove the
object-fit
property from theimg
tag and observe how the animation changes- Set the
object-fit
property back tonone
- Set the
- Change the
object-position
fromtop left
totop right
- Set the
object-position
property back totop left
- Set the
- Change the
opacity
inside the keyframes instead of thewidth
@keyframes grow {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes shrink {
from { opacity:1; }
to { opacity: 0; }
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Moving background images
- In the next example, we have a
section
tag and adiv.car
- The
section
tag:- has a
width
of80vw
and is centred at the middle of the viewport - has a repeating background image (
800px
x150px
) - is moved from right to left using the
background-position
property
section { width: 80vw; height: 150px; position: relative; border: 1px solid #000; background-image: url(https://itf-web-essentials.netlify.app/assets/landscape.jpg); background-repeat: repeat-x; animation: moveLandscape 8s linear infinite; overflow: hidden; } @keyframes moveLandscape { to { background-position: -800px 0; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 - has a
div.car
:- is absolutely positioned inside the
section
tag - has a non-repeating background image (
car1.png
) - is initially placed
-150px
outside thesection
by thetranslateX()
property
(you can't see it because theoverflow
property of thesection
is set tohidden
) - is moved from left to right by the
translateX()
property
(the right side is set to90vw
so the car is moving outside thesection
which has a width of80vw
)
.car { position: absolute; left: 0; bottom: 3px; width: 67px; height: 30px; background-image: url(https://itf-web-essentials.netlify.app/assets/car1.png); transform: translateX(-150px); animation: moveCar 4s linear infinite; } @keyframes moveCar { to { transform: translateX(90vw); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15- is absolutely positioned inside the
# Pac man
- The animated gif (
pacman.gif
) runs inside a rectangle box with the following properties:
keyframe | translateX() | translateY() | rotate() | action |
---|---|---|---|---|
0% | 0px | 0px | 0deg | start position |
25% | 360px | 0px | 0deg | move pac man to the right |
25.01% | 360px | 0px | 90deg | rotate pac man 90deg |
50% | 360px | 200px | 90deg | move pac man down |
50.01% | 360px | 200px | 180deg | rotate pac man 180deg |
75% | 0px | 200px | 180deg | move pacman to the left |
75.01% | 0px | 200px | 270deg | rotate pac man 270deg |
99.99% | 0px | 0px | 270deg | move pac man up |
100% | 0px | 0px | 0deg | same as start position |
- All the red values are the default values for
translateX()
,translateX()
orrotate()
and can be omitted - The keyframes at
0%
and at100%
can be left out entirely, because they only contain default values - The optimised result for the keyframes:
@keyframes pacman {
25% {
transform: translateX(360px);
}
25.01% {
transform: translateX(360px) rotate(90deg);
}
50% {
transform: translateX(360px) translateY(200px) rotate(90deg);
}
50.01% {
transform: translateX(360px) translateY(200px) rotate(180deg);
}
75% {
transform: translateY(200px) rotate(180deg);
}
75.01% {
transform: translateY(200px) rotate(270deg);
}
99.99% {
transform: rotate(270deg);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Exercise (optional)
- Like in the previous example, let pac man use the full viewport to move around
- The space between pac man and the browser border is
2rem
- Pac man has a square box of
38px
- As such,
translateX(360px)
andtranslateY(200px)
should be replaced bytranslateX(calc(100vw - 4rem - 38px))
translateY(calc(100vh - 4rem - 38px))
- The space between pac man and the browser border is
# Advanced examples (optional)
NEED-TO-KNOW
These examples are NOT PART OF THE SUBJECT MATTER to be mastered for this course, but they may challenge you or inspire you for future projects
# Moving background images
- Let's retake the basic example with moving background images
- In the middle of the animation the yellow car (car1.png) is switched to a red car (car2.png), riding in the opposite direction
keyframe | translateX() | translateY() | rotateY() | image | action |
---|---|---|---|---|---|
0% | -150px | 0px | 0deg | car1.jpg | start position |
50% | 90vw | 0px | 0deg | car1.jpg | Move the yellow car to the right |
50.01% | 90vw | -15px | 180deg | car2.jpg | Switch to the red car, rotate is 180deg , lift it 15px up and drive back |
100% | -150px | -15px | 180deg | car2.jpg | end position |
- The keyframe at
0%
can be left out entirely, because this only contains the default values - The optimised result for the keyframes:
@keyframes moveCar1 {
50% {
transform: translateX(90vw);
background-image: url(https://itf-web-essentials.netlify.app/assets/car1.png);
}
50.01% {
transform: translateX(90vw) translateY(-15px) rotateY(180deg);
background-image: url(https://itf-web-essentials.netlify.app/assets/car2.png);
}
to {
transform: translateX(-150px) translateY(-15px) rotateY(180deg);
background-image: url(https://itf-web-essentials.netlify.app/assets/car2.png);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# Progress bar
- This example is a Bootstrap progress bar clone, built with a repeating background gradient pattern
# Scrolling text
TIP
Disable the overfow
property on the div
tag to see how (based on adjusting the top margin of the first paragraph) this animation really works
# Animated SVG
- The SVG has a
width
andheight
of100px
- The SVG contains a square box of
80px
with a nearly white background and a second square box of60px
with anorangered
background - Let's make an animation of 3 seconds with this SVG
- Step 1: Animate
rect#orangeBox
- the
rect#orangeBox
starts with aheight
of0px
- After 1.5 seconds (
50%
), it starts to grow to its fullheight
(60px
)
#orangeBox { animation: increaseHeight 3s linear infinite; } @keyframes increaseHeight { from { height: 0; } 50%, to { height: 60px; } }
1
2
3
4
5
6
7 - the
- Step 2: Animate
svg#outline
- Rotate
svg#outline
by180deg
within 0.5 seconds (17%
)
(The child elements are also rotated!)
#outline { animation: rotate180deg 3s linear infinite; } @keyframes rotate180deg { form { transform: rotate(0); } 17%, to { transform: rotate(180deg); } }
1
2
3
4
5
6
7 - Rotate
- Step 3: Add a delay of 1 second to
rect#orangeBox
#orangeBox { animation: increaseHeight 3s linear infinite 1s; }
1
2
3
# Image overlay
- Let's try an animated overlay like we saw in the Photoshop tutorial gettotallyrad.com
- Because we don't know anything about JavaScript yet, let's do it with a simple hover effect
- Both images (the color image on top) are positioned absolutely inside the
figure
tag - It's very important to set the
object-fit
tonone
and theobject-position
toleft
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: none;
object-position: top left;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- When we hover the
figure
tag, thewidth
of the color image goes from100%
to0
figure:hover img:last-child {
animation: shrink 1s both;
}
@keyframes shrink {
from { width: 100%; }
to { width: 0; }
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- To make a smooth transition back when we leave the
figure
, it's also necessary to make a transition back from0
to100%
figure img:last-child {
animation: grow 1s;
}
@keyframes grow {
from { width: 0; }
to { width: 100%; }
}
1
2
3
4
5
6
7
2
3
4
5
6
7