Chapter 4. Working with CSS Timing Functions
So far, we’ve created our animations and transitions by specifying only a handful of things: the properties to animate, the initial and final property values, and the duration. The exact syntax was different depending on whether we were dealing with a CSS animation or a transition, but the general ingredients were the same. The end result was an animation.
In this chapter, we are going to add one more ingredient into the mix. We are going to kick things up a few notches by using something known as a timing function (also referred to as an easing function). In the following sections, you’re going to learn all about them!
What Is a Timing Function?
What a timing function is, or what it does, is a bit complicated to explain using just words. Before I confuse you greatly with the verbal explanation, take a look at the following example if you have a browser and internet connection handy: http://bit.ly/timing_functions.
What you see should look a little bit like the following:
As you can see in the video, there are three circles that start at the left, slide to the right, and return to where they started from. For all three of these circles, the key animation-related properties we’ve set are almost identical. They share the same duration, and the same properties are being changed by the same amount. You can observe that by noticing that the circles start and stop moving at the same time. Despite their similarities, though, the animation for each circle is obviously very different. What is going on here? How is this possible?
What’s going on (and causing the difference in how each circle animates) is the star of this chapter: the timing function. Each circle’s applied animation uses a different timing function to achieve the same goal of sliding the circles back and forth. So, let’s get back to our original question: What exactly is a timing function? A timing function is a function that alters the speed at which your properties animate.
For example, your timing function could specify that your property values change linearly with time (Figure 4-1).
This will result in your properties changing at a constant speed. If you want your property values to change in a more realistic way, you could throw in a timing function that mimics a deceleration, as in Figure 4-2.
In this case, the speed at which your property value changes slows down very rapidly. It’s kind of like hitting the brakes on your car and measuring the position before stopping. To summarize, there are four important things to keep in mind about timing functions:
- They don’t change where your property values start.
- They don’t change where your property values end.
- They don’t change your animation’s duration.
- They alter the speed at which your property values change.
Now, we can spend all day looking at timing functions and learning more about what they do. We aren’t going to do that. I have done that before, and it is actually really boring! Instead, let’s shift gears and look at how we can use these magical creatures (I mean…ingredients) in CSS.
Timing Functions in CSS
Despite how complicated timing functions seem, using them in CSS is pretty straightforward. The various timing functions you can use are:
ease
linear
ease-in
ease-out
ease-in-out
step-start
step-end
steps()
cubic-bezier()
You can specify these timing functions as part of defining your animation or transition, and we’ll look at the details of how exactly to do that in the following sections.
Timing Functions in CSS Animations
In a CSS animation, you can specify your timing function as part of the shorthand animation
property, or by setting the animation-timing-function
property directly. Here is a snippet of what the shorthand and longhand variants might look like:
/* shorthand */
#foo
{
animation
:
bobble
2s
ease
-
in
infinite
;
}
/* longhand */
#somethingSomethingDarkSide
{
animation-name
:
deathstar
;
animation-duration
:
25s
;
animation-iteration-count
:
1
;
animation-timing-function
:
ease
-
out
;
}
When you declare your timing function as part of the animation declaration, all of your keyframes will actually be affected by that timing function value. For greater control, you can specify your timing functions on each individual keyframe instead:
@keyframes
bobble
{
0%
{
transform
:
translate3d
(
50px
,
40px
,
0px
);
animation-timing-function
:
ease
-
in
;
}
50%
{
transform
:
translate3d
(
50px
,
50px
,
0px
);
animation-timing-function
:
ease
-
out
;
}
100%
{
transform
:
translate3d
(
50px
,
40px
,
0px
);
}
}
When you declare timing functions on individual keyframes, it overrides any timing functions you may have set in the broader animation declaration. That is a good thing to know if you want to mix and match timing functions and have them live in different places.
One last thing to note is that the animation-timing-function
declared in a keyframe only affects the path your animation will take from the keyframe it is declared on until the next keyframe. This means you can’t have an animation-timing-function
declared on your end (aka 100%) keyframe because there is no “next keyframe.” If you do end up declaring a timing function on the end keyframe anyway, that timing function will simply be ignored…and your friends and family will probably make fun of you behind your back for it.
Timing Functions in CSS Transitions
Transitions are a bit easier to look at since we don’t have to worry about keyframes. Your timing function can only live inside the transition
shorthand declaration or as part of the transition-timing-function
property in the longhand world:
/* shorthand */
#bar
{
transition
:
transform
.5s
ease
-
in
-
out
;
}
/* longhand */
#karmaKramer
{
transition-property
:
all
;
transition-duration
:
.5s
;
transition-timing-function
:
linear
;
}
There really isn’t anything more to say. As CSS properties go, transitions are pretty easy to deal with!
Meet the Timing Function Curve
Timing functions are very visual creatures. While we use them in terms of their CSS names (ease
, ease-in
, etc.), the way we’ll commonly run into them is visually through something known as a timing function curve (see Figure 4-3).
The timing function curve isn’t a generic representation for all timing functions. Each timing function has a very specific timing function curve associated with it. Figure 4-4 shows the timing function curves look like for the predefined CSS timing functions.
You can sorta see from Figure 4-4 how the different timing functions end up affecting how our animation runs.
Now, there are two timing functions that we did not include in Figure 4-4: steps
and cubic-bezier
. These timing functions are special (which is usually code for complicated)! We will look at each in more detail in the following sections.
The cubic-bezier Timing Function
The cubic-bezier
timing function is the most awesome of the timing functions we have. The way it works is a little complicated. It takes four numbers as its argument:
.foo
{
transition
:
transform
.5s
cubic
-
bezier
(
.
70
,
.
35
,
.
41
,
.
78
);
}
These four numbers define precisely how our timing function will affect the property that is getting animated. With the right numerical values, you can re-create all of our predefined timing functions (like ease
, ease-in-out
, etc.). Now, that’s not particularly interesting. What is really really interesting is the large variety of custom timing functions that you can create instead.
For example, with the cubic-bezier
timing function you can create a timing function that looks like Figure 4-5.
What this timing function highlights is that your property value will animate a bit beyond its final target and then snap back! That is something you can’t do using the predefined timing functions. This is just the tip of the iceberg on the kinds of timing functions you can create.
Now, you are probably wondering how we figure out the four numbers to throw into the cubic-bezier
timing function. It’s one thing to look at a timing function curve and make sense of what is going to happen. It is quite another to look at four boring numbers to make sense of the same things. Fortunately, we’ll never have to calculate the four numbers ourselves. There are a handful of online resources that allow us to visually define the timing function curve, which, in turn, generates the four numerical values that correspond to it.
My favorite of those online resources is Lea Verou’s cubic-bezier
generator:
You can use this generator to easily create a timing function by defining the timing function curve, previewing what an animation using that timing function would look like, and getting the numerical values that you can plug into your markup. Pretty simple, right?
The step Timing Function
The last timing function we will look at affects the rate at which our properties change but isn’t technically a timing function. This “non-timing function thing” is known as a step timing function (see Figure 4-6).
What a step function does is pretty unique. It allows you to play back your animation in fixed intervals. For example, in the step function graph in Figure 4-6, your animated property progression starts at 0%. At the 50% mark, it jumps to 50%. At the end of the animation, your property progression reaches 100%. There is no smooth transition between the various frames or “steps.” The end result is a bit jagged.
In CSS, you can define the step function by using the appropriately named steps
function:
.pictureContainer
img
{
position
:
relative
;
top
:
0px
;
transition
:
top
1s
steps
(
2
,
start
);
}
The steps
function takes two arguments:
- Number of steps
- A value of
start
orend
to specify whether the first step should occur at the beginning of the animation or whether the last step occurs when the animation ends
For example, if I want my animation to have five steps and have a step when the animation ends, my steps
function declaration would look as follows:
.pictureContainer
img
{
position
:
relative
;
top
:
0px
;
transition
:
top
1s
steps
(
5
,
end
);
}
One thing to note is that, the more steps you specify, the smoother your animation will be. After all, think of an individual step as a frame of your animation. The more frames you have over the same duration, the smoother your final result will be. That same statement applies for steps as well.
Conclusion
The icing on your animation- or transition-flavored cake is the timing function. The type of timing function you specify determines how lifelike your animation will be. By default, you have a handful of built-in timing functions you can specify as part of the animation-timing-function
or transition-timing-function
properties for your CSS animations and transitions. Whatever you do, just don’t forget to specify a timing function! The default ease
timing function isn’t a great substitute for some of the better ones you can use, and your animation or transition will never forgive you for it.
Also, before I forget, here is the full markup for the three sliding circles that you saw at the beginning of the chapter:
<
style
>
.circle
{
width
:
100px
;
height
:
100px
;
border-radius
:
50%
;
margin
:
30px
;
animation
:
slide
5s
infinite
;
}
#circle1
{
animation-timing-function
:
ease
-
in
-
out
;
background-color
:
#E84855
;
}
#circle2
{
animation-timing-function
:
linear
;
background-color
:
#0099FF
;
}
#circle3
{
animation-timing-function
:
cubic
-
bezier
(
0
,
1
,
.
76
,
1
.
14
);
background-color
:
#FFCC00
;
}
#container
{
width
:
550px
;
background-color
:
#FFF
;
border
:
3px
#CCC
dashed
;
border-radius
:
10px
;
padding-top
:
5px
;
padding-bottom
:
5px
;
margin
:
0
auto
;
}
@keyframes
slide
{
0%
{
transform
:
translate3d
(
0
,
0
,
0
);
}
25%
{
transform
:
translate3d
(
380px
,
0
,
0
);
}
50%
{
transform
:
translate3d
(
0
,
0
,
0
);
}
100%
{
transform
:
translate3d
(
0
,
0
,
0
);
}
}
</
style
>
<
div
id
=
"container"
>
<
div
class
=
"circle"
id
=
"circle1"
></
div
>
<
div
class
=
"circle"
id
=
"circle2"
></
div
>
<
div
class
=
"circle"
id
=
"circle3"
></
div
>
</
div
>
There is nothing crazy going on in this example, so I’ll leave you to it…and see you in the next chapter!
Get Creating Web Animations now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.