CSS Reference Data Type

<timing-function>

A <timing-function> in CSS is a (mathematical) function that specifies the speed over time of an object being animated or transitioned from one value to another. It describes how a transition or animation will progress over one cycle of its duration.

For example, if you were to move an object from point A to point B, you can have it move in a linear “steady” speed during a course of 2 seconds for example, or you can have it start up quickly from point A till it reaches halfway through and then have it gradually slow down till it reaches the point B. It’s the same as imagining yourself drive a car from your house to work (assuming that you don’t work from home, of course). Say it takes you 30 minutes to get there; you can either drive at a constant speed, or you can start off slowly knowing that you have a lot of time left, and then 20 minutes later step your speed up to make sure you get there on time.

This change of speed (acceleration or deceleration) in CSS animations and transitions is usually defined by a timing function that describes the speed over a course of time. When some animators usually talk about the “feel”, “physics” or “flow” of an animation, they may be referring to the particular timing function chosen to control the speed over time of the motion in question.

A timing function in CSS is usually a value for the transition-timing-function property and animation-timing-function property. It is used to define a function that describes how a transition will proceed over its duration, allowing a transition to change speed during its course.

The timing function in CSS describes how intermediate values during a transition will be calculated, and are usually referred to in CSS as easing functions.

Defining A Timing Function

A timing function can be defined in one of three ways: using a predefined keyword, using a stepping function, or using a cubic-bezier function. The official syntax is as follows:

<timing-function> = ease | linear | ease-in | ease-out | ease-in-out | step-start | step-end | steps(<integer>[, [ start | end ] ]?) | cubic-bezier(<number>, <number>, <number>, <number>)
                        

The steps() timing function

A stepping function is a timing function defined by a number that divides the transition’s time duration into equally sized intervals. The function also specifies whether the change in output percentage happens at the start or end of the interval. This subclass of step functions are sometimes also called staircase functions.

The syntax for this function is as follows:

steps(<integer>[, [ start | end ] ]?)
                        

The function takes one or two parameters, separated by a comma: a positive integer which specifies the number of intervals in the function, and an optional value of either start or end, which specifies the point at which the change of values occur within the interval. If no second parameter is included, it will default to end.

steps-function
Visual representation of examples of the steps() function

The best way to explain this function is with some live examples.

In the following two examples, the first parameter of the steps() function is set to 6, which means that the time of the transition will be divided into 6 intervals, and the transition will occur over 6 intervals, i.e. in 6 steps.

We’re using the CSS transition property to define a transition here. The transition is fired when you hover over the main container. The entire motion takes place over a course of 3 seconds as specified in the transition declaration. So, each interval is going to be 3/6 = 0.5s long.

Now, depending on the value of the second parameter of the function, the change in position will occur either at the beginning of each (of the 6) interval, or at its end.

In the first example, the second parameter of the steps() function is set to start; the value starts to change instantly when the transition is fired. So, at time = 0s, the start of the first interval, the first change of value occurs and the box is instantly moved 100px to the right.

While in the second example, the first change of value (in position) occurs at the end of the first interval, which is at time = 0.5s, the box is moved 100px to the right. You can notice this from the initial “lag” in the second animation.

View this demo on the Codrops Playground

The way this works is: the motion or transition of an element is split into n steps, depending on the number specified in the function. Then, you split the duration of the animation into n intervals, and then start taking the motion steps along the intervals based on the value of the second parameter of the function.

For example, in the above demo, the first box will start changing its values at t = 0s, which is the start of the first interval; so at t = 0s, the box moves its first 100px to the right (100px = 600px / n). Then, at the start of the second interval, at t = 0.5s, the box moves its second step by another 100px. It continues to go over the same steps, till it reaches the start of the last interval, at t = 2.5s, where it moves its last 100px and stays there, because at t = 3s, the duration of motion ends, so you can’t start a new interval and hence no additional steps are taken.

timing-function-demo-1-graph
Visual representation of the steps taken in the first demo. The blue lines represent the six intervals. The dot at the beginning of the lines are the points in time where each interval starts.

In the second demo the box will start its first out of 6 moves at t = 0.5s, which denotes the end of the first interval (remember, the second parameter is set to end). Then it makes its second move at t = 1s, which is the end of the second interval. It keeps doing that till it reaches the end of the sixth interval at t = 3s, where it takes its final step and the animation ends.

timing-function-demo-2-graph
Visual representation of the steps taken in the first demo. The blue lines represent the six intervals. The dot at the end of the lines are the points in time where each interval starts.

It is always a good idea to draw a simple graph, split it into as many intervals as you specify in your steps() function, to anticipate how the animation is going to executed. It also helps debug a lot of animations that may seem wrong at first, but make complete sense once the steps are plotted on a graph.

The steps() function can also be used to create some really cool image sprite animations. In this example by Simurai, you can see how the steps function is used to animate a cute creature waving at you. You can play around with the values of the steps() function and see how that affects the animation.

The cubic-bezier() timing function

The cubic-bezier() function specifies a cubic Bézier curve.

You can define your own timing function and create custom easing effects and even bouncing effects by defining custom cubic Bézier curves.

If you’re familiar with vector drawing software, then you’ve already seen your share of cubic Bézier curves. A cubic Bézier curve is defined by four control points, P0 through P3 (see image below).

bezier-curve-points
Visual representation of a cubic Bézier curve defined by four control points.

Given the start point (P0) and end point (P3) of a line, a Bézier curve defines two control points for each end (P1 and P2). P0 and P3 are always set to (0,0) and (1,1) relatively. The x coordinate of the starting point and the end point must always be between 0 and 1 inclusive. 0 and 1 represent the start and end points of an animation or transition, and therefore any value less than 0 or greater than 1 would exceed the time boundaries of a motion and therefore be invalid.

bezier-animation
How a cubic Bézier curve is created between two points. Source

So, a Bézier curve that is going to define the “feel” or “flow” of our transition or animation is defined by four points. Two of these points are fixed, so you won’t have to worry about them. You’re left with two control points: P1 and P2 that you need to specify in order to define a curve, and these two points are specified by X and Y coordinates (just like any point in a coordinate system).
The X value for the two points must also be in the range [0, 1]. The Y value, on the other hand, can exceed this range.

The cubic-bezier() function takes four parameters:

cubic-bezier(<number>, <number>, <number>, <number>)
                            

The four <number> parameters specify the two control points P1 and P2 of the curve as (x1, y1, x2, y2).

If you’re no math master and have no experience with graphic software and have no idea how to define the two control points, you may be asking yourself at this point: How do I specify the two control points to get the easing effect that I want? Setting the cubic-bezier values can be challenging and a visual representation of the curve makes things much easier.

Well, because the web community is so great, a lot of tools have been created to help you visually “plot” your two control points. These tools will also produce the right code for your cubic-bezier() function, and you can even visualize the easing effect in a demo to see how your motion will be controlled by your defined cubic Bézier curve. Here are 3 great tools that help creating custom easing values:

All of these tools offer drag and drop capability to move the control points around to get the curve shape you want.

For the following demo, we’ve used Lea Verou’s cubic Bézier tool to generate the cubic-bezier() functions.

cb-lea-verou
Screenshot of Lea Verou’s cubic Bézier generator tool

In the first example, we set the Y coordinate of one of the control points to more than 1, which results in a bouncing effect.

View this demo on the Codrops Playground

You can play around with Lea’s tool and produce and preview a lot of Bézier curve examples.

There is also a nice easing function cheat sheet available, which allows you to preview a lot of custom cubic Bézier curve effects, so check it out.

Timing function keywords

In addition to being able to define your own Bézier curves and timing functions, CSS comes with a few supported keywords defining some common easing functions, which are equivalent to specific timing functions defined using the cubic-bezier() or steps() functions.

ease
The ease function is equivalent to cubic-bezier(0.25, 0.1, 0.25, 1). This is the default timing function in CSS. So, if no timing function is specified in the transition-timing-function property or animation-timing-function property, then ease is the value set.
linear
The linear function is equivalent to cubic-bezier(0, 0, 1, 1). Using a linear timing function, the speed will be steady from start to end.
ease-in
The ease-in function is equivalent to cubic-bezier(0.42, 0, 1, 1). Using this timing function, the animation will start slowly and then gain more acceleration and get steady until the end of the duration.
ease-out
The ease-out function is equivalent to cubic-bezier(0, 0, 0.58, 1). Using this timing function, the animation will start fast and then decelerate and get steady until the end of the duration.
ease-in-out
The ease-in-out function is equivalent to cubic-bezier(0.42, 0, 0.58, 1). It’s a combination of ease-in and ease-out. The animation or transition will start slow, accelerate in the middle, and then slow down till the end.
step-start
The step-start function is equivalent to steps(1, start). Using this timing function, the animation or transition will abruptly change to the end state and stays in that position until the end of the animation.
step-end
The step-end function is equivalent to steps(1, end). Using this timing function, the animation or transition stays in its initial state until the end, where it directly jumps to its final position.

You can play with the values in the following demo and see how they affect the flow of the transition.

View this demo on the Codrops Playground

Browser Support

Basic support: Chrome v4, FF 4, IE 10, Opera 10.5, Safari 3.1, Android 4, iOS 2.

Support for cubic-bezier() with values exceeding the [0,1] range: Chrome v16, FF 4, IE 10, Opera 12.1, Safari Nightly, Android yes, iOS None.

Support for steps(): Chrome v8, FF 4, IE 10, Opera 12.1, Safari 5.1, Android 4, iOS 5.

Further Reading

Written by

Last updated March 6, 2020 at 3:27 am by Mary Lou

Do you have a suggestion, question or want to contribute? Submit an issue.