# Transitions
- Transitions allow you to gradually or smoothly change some properties from one style to another
- The transition is on a different state (like
:hover
,:active
,:focus
,:checked
, ...) of the element itself or on a different state of the parent element - Most of the properties can be changed smoothly but, the
font-family
and thebackground-image
for example can not - Transitions are often (not always) used in combination with transformations
- The transition properties are:
EMMET instruction | result | default | description |
---|---|---|---|
trsp + TAB | transition-property: ; | all | property to change |
trsdu + TAB | transition-duration: ; | 0 | duration of the transition in seconds (s ) or milliseconds (ms ) |
trsde + TAB | transition-delay: ; | 0 | delay (s orms ) before the transition starts |
trstf + TAB | transition-timing-function: ; | ease | speed curve of the transition effect |
trs + TAB | transition: ; | shorthand for all the above properties |
# One property
- Span 1: Change the
background-color
over a period of1000ms
(or1s
)
span:first-child {
transition: background-color 1000ms;
}
span:first-child:hover {
background-color: coral;
}
1
2
3
4
5
6
2
3
4
5
6
- Span 2: Change the
border-radius
over a period of2000ms
(or2s
)- Notice that the
background-color
changes immediately!
- Notice that the
span:nth-child(2) {
transition: border-radius 2000ms;
}
span:nth-child(2):hover {
background-color: skyblue;
border-radius: 50%;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- Span 3: Transform (rotate and scale) the
span
tag over a period of500ms
(or.5s
)
span:last-child {
transition: transform 500ms;
}
span:last-child:hover {
transform: rotate(30deg) scale(1.2);
}
1
2
3
4
5
6
2
3
4
5
6
<div> <span>1</span> <span>2</span> <span>3</span> </div>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; text-align: center; }
div { border: 1px solid darkgray; background-color: rgba(169, 169, 169, 0.3); display: inline-block; margin: 1rem; }
span { display: inline-block; width: 5rem; line-height: 5rem; margin: 1rem; border: 1px solid #000; background-color: lightgreen; }
span:first-child { transition: background-color 1000ms; }
span:first-child:hover { background-color: coral; }
span:nth-child(2) { transition: border-radius 2000ms; }
span:nth-child(2):hover { background-color: skyblue; border-radius: 50%; }
span:last-child { transition: transform 500ms; }
span:last-child:hover { transform: rotate(30deg) scale(1.2); }
REMARK
- Move the transition from the normal state to the hover state and look how the transition reacts this time
- The transition ONLY takes place when entering the
span
tag and NOT when you leave thespan
tag!
- The transition ONLY takes place when entering the
span:last-child {
/* transition: transform 500ms; */
}
span:last-child:hover {
transition: transform 500ms;
transform: rotate(30deg) scale(1.2);
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# Two or more properties
- You can transition two or more CSS properties by separating them with a comma
- Span 1: Change three properties over the same period
- Span 2: Change the same three properties but with different timing
span:first-child {
transition: background-color 1s, border-radius 1s, transform 1s;
}
span:last-child {
transition: background-color 1s, border-radius 2s, transform 6s;
}
span:hover {
background-color: skyblue;
border-radius: 50%;
transform: rotate(30deg) scale(1.5);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<div> <span>1</span> <span>2</span> </div>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; text-align: center; }
div { border: 1px solid darkgray; background-color: rgba(169, 169, 169, 0.3); display: inline-block; margin: 1rem; }
span { display: inline-block; width: 5rem; line-height: 5rem; margin: 1rem; border: 1px solid #000; background-color: lightgreen; }
span:first-child { transition: background-color 1s, border-radius 1s, transform 1s; }
span:last-child { transition: background-color 1s, border-radius 2s, transform 6s; }
span:hover { background-color: skyblue; border-radius: 50%; transform: rotate(30deg) scale(1.5); }
# All properties
- When targeting all properties at once, you can use the keyword
all
or just leave the keyword out becauseall
is the default value
img {
margin: 1rem;
border: 1px solid #000;
transition: 2s;
}
img:hover {
filter: sepia(100%);
opacity: .5;
border-radius: 2rem;
transform: rotate(180deg);
box-shadow: 0 0 20px rgba(0, 0, 0, 1);
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<figure> <img src="https://picsum.photos/id/102/200/200" alt="Raspberries"> </figure>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; text-align: center; }
figure { border: 1px solid darkgray; background-color: rgba(169, 169, 169, 0.3); display: inline-block; padding: 1rem; }
img { margin: 1rem; border: 1px solid #000; transition: 2s; }
img:hover { filter: sepia(100%); opacity: .5; border-radius: 2rem; transform: rotate(180deg); box-shadow: 0 0 20px rgba(0, 0, 0, 1); }
DESIGN TIP
For a minimalistic approach to CSS transitions:
- Use transitions purposefully, enhancing only key elements like buttons or navigation menus.
- Keep transition durations between 200ms to 500ms for quick, smooth feedback.
- Ensure consistency in transition effects across the website to maintain a cohesive user experience.
REMARK
When speed is important (e.g. on older smartphones), it's best to target all properties individually like we did in the previous example (as the all
keyword loops over ALL changeable properties of the element, not only the properties you write in the hover state)
# Sequential transitions
- The
transition-delay
property specifies the duration to wait before starting a property's transition effect
WARNING
When using the transition-duration
AND the transition-delay
with the shorthand property, the transition-duration
ALWAYS comes first!
- In the example below, we use some of the transitions of the previous example but now in sequential order
- The transition on the
border-radius
starts immediately and takes300ms
- The transition on the
box-shadow
starts after300ms
and takes800ms
- Then there is a pauze of
400ms
because thetransform
starts at1.5s
- The transition on the
img {
margin: 1rem;
border: 1px solid #000;
transition: border-radius 300ms,
box-shadow 800ms 300ms,
transform 1s 1.5s;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
<figure> <img src="https://picsum.photos/id/102/200/200" alt="Raspberries"> </figure>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; text-align: center; }
figure { border: 1px solid darkgray; background-color: rgba(169, 169, 169, 0.3); display: inline-block; padding: 1rem; }
img { margin: 1rem; border: 1px solid #000; transition: border-radius 300ms, box-shadow 800ms 300ms, transform 1s 1.5s; }
img:hover { filter: sepia(100%); opacity: .5; border-radius: 2rem; transform: rotate(180deg); box-shadow: 0 0 20px rgba(0, 0, 0, 1); }
# Timing function
- You can use several keywords for the
transition-timing-function
function- A full list can be found at the MDN web docs transition timing function page
- Default timing function is
ease
- There is one special function (
cubic_bezier
) which can be fully customized
- A few examples:
- All span tags behave as a block element with a default
width
of130px
(IMPORTANT: the transitions only work if you specify awidth
other thanauto
!) - On the hover state, the span tag grows to his full
width
of100%
but every span tag has his own timing function
- All span tags behave as a block element with a default
span {
...
display: block;
width: 130px;
}
span:hover {
width: 100%;
}
span:first-child {
transition: width 2s linear;
}
span:nth-child(2) {
transition: width 2s ease;
}
span:nth-child(3) {
transition: width 2s steps(4);
}
span:nth-child(4) {
transition: width 2s cubic-bezier(0.1, 0.7, 1.0, 0.1);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div> <span>linear</span> <span>ease-in-out</span> <span>steps(4)</span> <span>cubic-bezier()</span> </div>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; }
div { border: 1px solid darkgray; background-color: rgba(169, 169, 169, 0.3); margin: 1rem; padding: .5rem; }
span { margin-bottom: .5rem; padding: .5rem; border: 1px solid #000; background-color: skyblue; display: block; width: 130px; }
span:hover { width: 100%; }
span:first-child { transition: width 2s linear; }
span:nth-child(2) { transition: width 2s ease-in-out; }
span:nth-child(3) { transition: width 2s steps(4); }
span:nth-child(4) { transition: width 2s cubic-bezier(0.1, 0.7, 1.0, 0.1); }
TIP: Custom cubic_bezier() timing function (optional)
- To create your own custom timing function, you can use cubic-bezier.com but it can also be done inside the browser's DevTools (Firefox: left image, Chrome: right image)
- Select one of the
span
tags - Click on the icon near the timing function
- Play with the start and end handles to create your custom function
- Copy the
cubic_bezier()
code and paste it in to your transition function
- Select one of the
# Targeting a child element
- Sometimes you need to move the hover state to the parent element to create an attractive effect
- When you hover the
span
element in the bottom left corner, the transformation sometimes "shakes" a bit - Let's make the effect on the following example a bit nicer:
- Replace
span:hover {...}
withdiv:hover span {...}
- Replace
div:hover span {
transform: rotate(-45deg);
}
1
2
3
2
3
<div> <span>rotate(45deg)</span> </div>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: Verdana, Geneva, sans-serif; line-height: 1.5; padding: 1rem; text-align: center; }
section { display: flex; flex-wrap: wrap; }
div { border: 1px solid darkgray; background-color: rgba(169, 169, 169, 0.42); display: inline-block; margin: 2rem; }
span { display: inline-block; width: 150px; line-height: 150px; font-size: .9rem; text-align: center; border: 1px solid #000; background-color: rgba(248, 204, 52, 0.66); transform-origin: top right; transition: 1s; }
span:hover { /* replace with: div:hover span */ transform: rotate(-45deg); }
# Example
# Rising buttons
- This page contains a basic
navbar
as we saw at the Flexbox course page - When you hover an
a
tag, it is scaled along the X axis, moved up by.2rem
and it gets some new colors and a little drop shadow
nav a {
...
color: floralwhite;
border: 1px solid coral;
transition: 300ms;
}
a:hover {
transform: scaleX(1.05) translateY(-.2rem);
background-color: floralwhite;
border-color: dimgray;
color: dimgray;
box-shadow: 0 5px 5px rgba(0, 0, 0, .2);
}
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
<nav> <ul> <li> <a href="#!">HOME</a> </li> <li> <a href="#!">TWITTER</a> </li> <li> <a href="#!">SLACK</a> </li> </ul> </nav>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; line-height: 1.5; padding: 2rem; background-color: coral; }
nav { font-weight: bold; }
nav ul { display: flex; list-style-type: none; text-align: center; }
nav li { flex: 1 1 auto; display: flex; }
nav a { flex: 1 1 auto; line-height: 2; color: floralwhite; border: 1px solid coral; transition: 300ms; }
a:hover { transform: scaleX(1.05) translateY(-.2rem); background-color: floralwhite; border-color: dimgray; color: dimgray; box-shadow: 0 5px 5px rgba(0, 0, 0, .2); }
# Overline menu item
- When you hover an
a
tag, it changes colors and gets an overline.
<nav> <ul> <li> <a href="#!">Home</a> </li> <li> <a href="#!">Twitter</a> </li> <li> <a href="#!">Slack</a> </li> </ul> </nav>
* { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
body { font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; line-height: 1.5; padding: 2rem; }
nav ul { list-style: none; display: flex; }
nav ul li { margin-right: 20px; }
nav ul li a { color: #333333; border-top: 2px solid white; padding-top: 7px; text-decoration: none; transition: .5s; }
nav ul li a:hover { color: black; border-top-color: black; }