Oscar Jite-Orimiono I'm a self taught frontend web developer. I build websites so everyone finds a home online. The digital space is massive, full of endless possibilities, let's explore it together!

Understanding animation and transition timing functions in CSS

7 min read 2003

Understanding animation transition timing functions CSS

A dictionary will define animation as the illusion of motion. Like cartoons, animations are multiple drawings filmed in succession to create the illusion of movement. Animations are used to make websites more engaging and can be used to draw the user’s attention, oftentimes showing that a button is clickable.

Animations can be subtle or elaborate — you decide. In this post, we’ll look at timing functions. Timing functions help control how animations behave over a specified duration. Before we go further, let’s look at the CSS properties responsible for creating animations in the first place.

There are two ways to animate web elements in CSS: the animation and transition properties. The animation property allows you to change the properties of an element over a specific duration, while transition defines how an element changes over a specific duration.

You might be wondering, what’s the difference? I’ll tell you. animation needs @keyframes, meaning a start and endpoint must be specified. Keyframes are used for multistep animations.

Simpler web animations can be created using transition. The animation must be triggered by something, like a click or :hover.

animation and transition are shorthands for an array of properties that control duration, delay, iteration, etc. But, as stated earlier, this post will focus solely on timing functions.

What are timing functions?

The animation-timing-function specifies the speed curve of an animation. The transition-timing-function specifies the speed curve of a transition effect. Déjà vu.

A curve, graphically, is a connection of multiple points. Each animation or transition period is divided into points that make up the speed curve, and timing functions define how the element behaves at each of these points. The animation property is divided into @keyframes, like the FPS (frames per second) of a camera.

The animation-timing-function and transition-timing-function can stand alone as separate CSS properties or be included as a value in the animation or transition shorthand property.

So, you could have your animation like this:

We made a custom demo for .
No really. Click here to check it out.

animation: <name> <duration> <timing-function>;

Or like this:

animation-name: name;
animation-duration: 500ms;
animation-timing-function: ease;

The same with transition:

transition: <property> <duration> <timing-function>;

Or:

transition-property: transform;
transition-duration: 500ms;
transition-timing-function: ease;

There are nine timing functions in CSS, including:

  1. linear
  2. ease
  3. ease-in
  4. ease-out
  5. ease-in-out
  6. cubic-bezier()
  7. step-end
  8. step-start
  9. steps()

The first six are easing functions and can be used with both animation and transition. The last three are step functions used with the animation property.

linear timing function

linear animations move at a constant speed. This function isn’t exactly an easing function, as there’s no variation from start to finish. The speed curve will be a straight line graph.

Linear speed curve

ease timing function

Animations with the ease function start slowly, speed up, and then end slowly. This is the default timing function used if no timing function is added to the animation.

Ease speed curve

The speed of the animation at the end is slower than at the start.

Let’s demonstrate these two timing functions. We’re going to have a race across the stars!

Meet our racers, ease and linear:

Racer ease linear

Let’s use a simple HTML markup:

<body>
  <div class="container">
    <div class="rockets rocket-1"><img src="Rocket1.png"></div>
    <div class="rockets rocket-2"><img src="Rocket2.png"></div>
  </div>
</body>

Then some basic CSS:

body {
  margin: 0px;
  padding: 0px;
}
*{
  box-sizing: border-box;
}
.container{
  width: 100%;
  height: 300px;
  background: rgba(224,214,233, 0.5)
}
.rockets{
  width: 500px;
  height: 100px;
  transition-duration: 2s;
  transition-property: transform;
  display: flex;
  align-items: center;
}
.rockets img{
  height: 100px;
  border-right: 1px solid red;/*To track the speed easily*/
}

Now, the animation proper. We’ve gone with transition, so the trigger is going to be :hover.

.container:hover .rockets{
  transform: translateX(500px);
}
.rocket-1{
  transition-timing-function: linear;
}
.rocket-2{
  transition-timing-function: ease;
}

The resulting animations:

See the Pen
Linear vs Ease timing function
by Oscar-Jite (@oscar-jite)
on CodePen.

At first glance, it looks like ease is faster than linear, but they both have the same animation-duration. When you watch closely, you’ll see that they both end at the same point. It seems we have a tie!

ease-in, ease-out, and ease-in-out timing functions

Animations with the ease-in timing function start slow and speed up towards the end. ease-out is the opposite, with a fast start and slow end.

Ease in ease out speed curves

ease-in-out animations start slow, speed up in the middle, and end slow. It’s similar to the ease timing function, but here the curve is symmetrical. The speed of the animation at the start is equal to the speed at the end.

Ease in out speed curve

Ready for the second race?

Ease in ease out ease in out

.rocket-1{
  transition-timing-function: ease-in;
}
.rocket-2{
  transition-timing-function: ease-out;
}
.rocket-3{
  transition-timing-function: ease-in-out
}

Ready, set, :hover, and go!

See the Pen
Ease-in, Ease-out and Ease-in-out
by Oscar-Jite (@oscar-jite)
on CodePen.

cubic-bezier()timing function

The cubic Bezier curve is defined by control points that draw a smooth curve. All easing functions have Bezier curves.

Animation cubic bezier curve

The linear timing function is a Bezier curve with only two control points. It can also be a quadratic curve, with three control points.

cubic-bezier(P1,P2,P3,P4)

P1 and P3 must be within 0 and 1. P2 and P4 can be as high as possible and can also hold negative values. It’s best to keep all control points between -1 and 1 to avoid super jerky and bouncy animations.

Let’s demonstrate. We’ll go with random values for the control points.

.rocket-1{
  transition-timing-function: cubic-bezier(.66,.39,.21,.67);
}
.rocket-2{
  transition-timing-function: cubic-bezier(1,-0.42,.42,-0.39);
}
.rocket-3{
  transition-timing-function: cubic-bezier(.57,1.34,.21,0);
}

Hover on the rockets to see the result:

See the Pen
Cubic-bezier timing function
by Oscar-Jite (@oscar-jite)
on CodePen.

You can choose to manually enter the values for the control points, but it might take time to find the right easing for your animation. There are two ways you can choose the perfect cubic-bezier() speed: using the inspector tool or using a cubic Bezier generator.

Using the inspector tool

First, the animated element should be given any timing function. Access the dev tools by right clicking on the web element and select Inspect or Inspect element, depending on the browser.

If you’re using the animation or transition shorthand keyword, there will be a dropdown icon beside the property name. Click that to reveal a list of multiple property values that include the timing function. Otherwise, you have it as a separate property.

Inspector tool

You’ll find a curve icon beside the name of the timing function that opens up a cubic Bezier editor. You can compare the default easing functions.

Cubic bezier editor grid

Or cycle through their variations. Click on and adjust the handles to get the cubic-bezier(). There’s a visualizer to help you decide.

Cubic bezier variations

When you find a suitable speed curve, copy the cubic-bezier() and paste it into your project.

Final cubic bezier
N.B., screenshots are from Chrome. It would look different on other browsers.

Using a cubic Bezier generator

Head over to cubic-bezier.com and you’ll find a great tool that helps you create Bezier speed curves. Play with the handles until you get a curve you like. Preview and compare with the default easing functions. Copy and paste into your project and you’re all set!

Cubic bezier generator

step-end, step-start, and steps() timing functions

These timing functions break animations into equal sections or steps.

The step-end timing function starts the animation after the first @keyframe and skips a step at the end. step-start is the opposite: the steps start as soon as the animation begins.

Let’s demonstrate how it works:

.rockets{
  width: 500px;
  height: 100px;
  animation-duration: 2s;
  animation-name: flight;
  animation-iteration-count: infinite;
  animation-direction: alternate-reverse;
  display: flex;
  align-items: center;
}
.rocket-1{
  animation-timing-function: step-end;
}
.rocket-2{
  animation-timing-function: step-start;
}
@keyframes flight{
  0%{transform: none;}
  25%{transform: translateX(125px);}
  50%{transform: translateX(250px);}
  75%{transform: translateX(375px);}
  100%{transform: translateX(500px);}
}

The result:

See the Pen
step-end vs step-start
by Oscar-Jite (@oscar-jite)
on CodePen.

The step-start rocket is a step ahead because it jumps to the first @keyframe as soon as the animation begins.

If you want to be a bit more intricate, you can use steps() to specify the number of steps or sections you want in your animation. For instance:

.rocket-1{
  animation-timing-function: steps(5);
}
.rocket-2{
  animation-timing-function: steps(10);
}
.rocket-3{
  animation-timing-function: steps(20);
}
@keyframes flight{
  0%{transform: none;}
  100%{transform: translateX(500px);}
}

See the result here:

See the Pen
Steps() timing-function
by Oscar-Jite (@oscar-jite)
on CodePen.

There are keywords you can use with the steps() timing function in addition to the number of steps:

  1. jump-start
  2. jump-end
  3. jump-both
  4. jump-none

jump-start and jump-end work the same way as step-start and step-end. jump-both means the animation skips a step at both ends. jump-none means the animation doesn’t skip a step, and each step is evenly spaced throughout the duration.

.rocket-1{
  animation-timing-function: steps(5,jump-end);
}
.rocket-2{
  animation-timing-function: steps(5,jump-start);
}
.rocket-3{
  animation-timing-function: steps(5,jump-both);
}
.rocket-4{
  animation-timing-function: steps(5,jump-none);
}
@keyframes flight{
  0%{transform: none;}
  100%{transform: translateX(500px);}
}

The result is here:

See the Pen
Step jump
by Oscar-Jite (@oscar-jite)
on CodePen.

Global timing functions

These global properties work for every CSS property. They include:

  • inherit: This gives a child element the same properties of the parent if they can be inherited. If the properties aren’t inherited, they revert back to initial
  • initial: You might think using initial is just another way of using the default value of the CSS property, but that’s not always the case. With timing functions, initial is the same as the default value ease
  • revert: This sets the properties of an element to the default CSS values of the browser
  • unset: This keyword works like revert but with a twist. It affects both inherited and non-inherited properties

The above elements are CSS inheritance properties. Unfortunately, animation-timing-function and transition-timing-function are non-inherited properties, so we won’t see anything new, but let’s look at them one after the other.

So, if the property is inherited, unset gives it the inherit value. And if it is non-inherited, the property is set to its initial value.

Browser support

The following properties and functions are supported on all modern browsers:

Safari 4–5 doesn’t support any of the step timing functions. The jump keywords are supported on every browser except Internet Explorer, Microsoft Edge 12–18, Firefox 2–64, Chrome 4–76, Safari 3.1–13.1 and Opera 10–63.

Bonus property

Since we’re dealing with timing, there’s a property that can be used alongside the timing functions: -delay.

animation-delay and transition-delay make animations wait for a moment before they start.

You can include it with the shorthand:

animation: <name> <duration> <timing-function> <delay>;

transition: <property> <duration> <timing-function> <delay>;

No matter the order of the properties, the second time value in the declaration will always be the delay property. So, if we had a declaration like this:

transition: transform 2s 1s ease;

The transition-delay is 1s. This also applies to animation.

Let’s demonstrate with the rockets:

.rocket-1{
   transition-timing-function: cubic-bezier(.66,.39,.21,.67);
   transition-delay: 500ms;
}
.rocket-2{
   transition-timing-function: cubic-bezier(.66,.39,.21,.67);
   transition-delay: 700ms;
}
.rocket-3{
  transition-timing-function: cubic-bezier(.66,.39,.21,.67);
  transition-delay: 1s;
}

See the Pen
Delayed animation
by Oscar-Jite (@oscar-jite)
on CodePen.


This could be used to load different sections of a webpage without having to define a different animation or transition for each section.

Conclusion

Animations are a great way to interact with visitors and deliver engaging content. It is important that they are kept to a minimum, however, as animating too many properties on the same webpage or at the same time can have a detrimental effect on performance. Also, I recommend keeping the duration short. One second is longer than you think, and animations should ideally be in milliseconds.

We’ve looked at how timing functions control the speed and behavior of web animations. From easing to step functions, can you see them in practical scenarios? Buttons, progress bars, text cards, and so much more can be animated. Try them out and create something great!

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Oscar Jite-Orimiono I'm a self taught frontend web developer. I build websites so everyone finds a home online. The digital space is massive, full of endless possibilities, let's explore it together!

Leave a Reply