# Easing Functions (aka Timing Functions) in CSS3 by [kirupa](https://www.kirupa.com/me/index.htm) | 10 March 2013 When you are creating an animation, what happens to your animated properties while your animation is running is almost as important as what happens at the end. For example, your property values could change linearly with time: ![](https://www.kirupa.com/html5/images/easing_linear_ease.png) In this case, what you see is an animation that neither seems to speed up nor slow down. Your animation moves at a steady, constant, and (possibly) boring rate. You can kick things up a notch by having your properties change with a little more style: ![](https://www.kirupa.com/html5/images/easing_out.png) In this example, your property changes very quickly at the beginning and then slows off towards the end. In both of these cases, the end result is the same. At the beginning, your property has a value. At the end, after whatever duration is specified elapses, your property has a final value. If you closed your eyes just when the animation started and opened them once the animation completed, you'll have no idea which of the two animation variants actually played. The only thing that is different between the linear case and the non-linear case is the speed at which the property values changed. There is a name for these speed variations that determine how an initial value reaches its final value. That name is **easing function**, and this tutorial is all over it. Onwards! ## Making Sense of Easing Functions In the previous section, you saw two colorful graphs that visualized how properties change in the presence of an easing function. In one you had a linear ease that didn't do much. In the other, you had a non-linear ease that slowed your property changes down as your animation was running. In this section, let's turn the camera around a bit and focus exclusively on easing functions without getting distracted by actual property values and durations. As part of this look, you will see some sweet diagrams containing lines, labels, numbers, and other things that you may not have seen since school. Yippee! ### Meet the Easing Function Curve Whenever anybody talks about easing functions, it's only matter of time before a graph of what is known as the **easing function curve** is drawn. Knowing how to draw and understand this curve is an important part of mastering easing functions, so let's look at how to define this curve. To help with all this, we need a patsy. We need an example. #### The Example Our example is going to be pretty simple. What we have is an element whose `opacity` property value **linearly** changed from 1 to 0 over a period of 2 seconds with a linear ease applied. This could either be an animation or a transition - it really doesn't matter. A chart of this example where we plot the opacity value and duration would look as follows: ![](https://www.kirupa.com/html5/images/opacity_0_1.png) From looking at this chart, it is pretty easy to figure out what the value of your `opacity` property would be at any given point during the 2 second animation. At the **1** second mark, your `opacity` property would have a value of **.5**. At the **1.5** second mark, your `opacity` property would be **.25**, and so on. #### Visualizing Easing Functions Here is where things get interesting. Easing functions define the rate at which your property changes. What a property value is at any given time isn't nearly as important as **how that property changed from its initial value to the final value over the lifetime of the animation**. This means that all of the earlier charts I've provided are no good. To draw a chart through the eyes of an easing function, let's generalize things a bit and switch over to using percentages. Instead of plotting the property value over a period of time, let's plot a ratio of both of them instead. Let's plot the **percentage** of how much progress the property has made to reach its final value compared to how much of the animation has been completed. Our earlier chart transformed to take into account these new expectations will look as follows: ![](https://www.kirupa.com/html5/images/percentage.png) While our graph looks different, the details that you had before earlier is still represented here. You just have to dig a little bit deeper. In our example, the `opacity` property goes from starting at 1 to ending at 0. At the beginning with 0% of your animation having been completed, your `opacity` property is 0% of the way there to reaching its final value of 0: ![](https://www.kirupa.com/html5/images/beginning.png) That is why our blue line starts of at 0% for your property progression. When your animation completes, your opacity property is at 0...aka the final value. Another way of saying that is that it reached 100% of where it needed to go, and it did that right at the end with 100% of your animation having been completed: ![](https://www.kirupa.com/html5/images/in_the_end.png) As you can see, our blue line ends at 100% for both completion as well as property progression. Because the change is linear, what you get is a straight line from the (0%, 0%) point at the bottom-left to the (100%, 100%) point at the top-right. With this alternate representation for looking at your animation, the thing to note is that it no longer matters what the property value you care about actually is at the beginning or the end. The value could be something between 0 and 1 for opacity; something between #FFFFF and #00000 for a color; something positive and negative; and a whole lot more. It also no longer matters what the duration is. Your animation being .2 seconds long or 600 seconds long are no longer important. At this point, we've pretty much generalized all the pesky details away into the simple ratio between progress and completion. **All that matters is what percentage of the final property value has been reached at any given point during the animation's lifetime**. ### Visualizing Easing Functions...for Real This Time! This is far less dramatic than what this section heading may imply. The percentage-based graphs you saw in the previous section contain the easing function. I just didn't highlight it because the timing wasn't right: ![](https://www.kirupa.com/html5/images/easing_function.png) The blue line is the mythical easing function curve. Now that you know this, let's try to understand this curve more. #### Linear Cases For a linear ease, as you have seen so far, the end result is a straight line. Your animation's completion and how far the property has progressed move hand-in-hand: ![](https://www.kirupa.com/html5/images/progression_2a.png) To highlight this, the arbitrarily chosen 30% mark represents both how far the property has progressed as well as how much of the animation has run to completion. Mapping this to what you will see on your screen, because the property is changing from 1 to 0 over 2 seconds, 30% represents an opacity value of .7 and an elapsed time of .6 seconds. This is just some simple multiplication. For the most part, though, **you will never actually need** to do any simple multiplication to translate from this percentage based world to the actual property values. All you really need to know from looking at the easing function curve is how it will affect your animation. With a straight line like this, it is very clear how your final animation will be affected. #### The Awesome Non-Linear Cases Of course, not everything is as simple as what you have with a linear easing function. For the more exotic non-linear cases, how far your property has progressed will diverge from how much of your animation has actually been completed: ![](https://www.kirupa.com/html5/images/non-linear2.png) For example, let's take a look at the 75% completion mark and see where things stand: ![](https://www.kirupa.com/html5/images/non-linear_labels.png) Eyeballing things from this graph, your animation completing 75% of its life doesn't mean that the property has reached 75% of its final value. The value is more like 45% percent instead. From looking at the easing function curve, notice that your property changes don't catch up to your animation's completion percentage until the very end. What this means that your animation starts off pretty slow and then speeds up only much later. A different easing function may do something different, and you'll get to see a lot of these different easing functions shortly. ### What You Can and Can't Do We are almost done with the theoretical book learning. The last thing we are going to look at before getting even more serious is a boring overview of what you can and can't do using easing functions in CSS. #### You Always Start at 0% and End at 100% The most important limitation you should know about is that your **property progression will always start at 0% in the beginning and end at 100% upon animation completion**. It doesn't matter what your easing function does in the middle. The beginning and end are clearly defined and can't be changed: ![](https://www.kirupa.com/html5/images/side_to_side4.png) What does this mean? This means your easing function can ** never** get your animated properties to start off at anything but their initial values. Likewise, at the end of the animation, your easing function will **never** get your animated properties to stop at anything but the final value. Between the beginning and the end, the easing function may do all sorts of crazy things that affect the animated properties in similarly crazy ways. It is just that, at the beginning and the end, order is maintained. #### There Is No Box Speaking of crazy things that happen outside of the beginning and the end, your property values can change beyond 100% and below 0%: ![](https://www.kirupa.com/html5/images/beyond_100.png) Being able to go beyond the range prescribed by your property's initial value and final value is a very important detail that can help make your animations more realistic! One of the [ 12 Basic Principles of Animation](http://en.wikipedia.org/wiki/12_basic_principles_of_animation#Follow_through_and_overlapping_action) is called **Follow through**. Follow through refers to an animation technique where things don't stop animating suddenly. They exceed their final target slightly before snapping back into place. This useful technique is something that can only be done by going beyond the 0% and 100% range. ## My Name is Curve...Cubic Bezier Curve! So far, we've looked at easing functions in a very general, imprecise sense. As part of learning about them, such hand waving is acceptable. Now that we are getting close to actually using easing functions, we need to get a little bit more precise. Let's start with defining our easing function curve more formally. Our easing function curve isn't simply called an easing function curve. That is simply its stage name. The easing function curves are more formally known as **cubic bezier curves**. While I won't go into great mathematical detail about cubic bezier curves, I will provide you with just enough information so that you can effectively use them to create awesome animations. Let's get started by taking a look at the following easing func...err cubic bezier...curve: ![](https://www.kirupa.com/html5/images/cubic-bezier_3.png) This curve doesn't look the way it does because it fell off the wagon like that. It looks this way because of various precisely placed points that mathematically influence its shape: ![](https://www.kirupa.com/html5/images/cubic-bezier_lines.png) The thing to know is that a cubic bezier curve is made up of four points. I've labeled those four points, as seen in the above diagram, as P0, P1, P2, and P3. Each point is made up of two values that represent its horizontal and vertical position in our chart - two values we'll simply call **x** and **y**: ![](https://www.kirupa.com/html5/images/cubic-bezier_points_values.png) I described the point values in terms of decimals as opposed to percentages because you'll rarely see percentages use to mark a cubic bezier point. From the above diagram, you can see how I got the values for both P1 and P2 pretty easily. I just translated the values from the completion and property progression axes into decimals. Notice that I didn't even bother labeling P0 and P3 because they are always going to be (0, 0) and (1, 1) respectively in our HTML world. The point values are extremely important not just because they better explain our charts. They are important because it is **these values that you specify in your CSS** - something which you will see shortly! ## Easing Functions in CSS Finally, we get to move beyond analyzing graphs and move into CSS territory. The CSS properties that define an easing function are the cleverly named `transition-timing-function` and `animation-timing-function`. The names of these properties is a dead giveaway (like a will...booyah!) on when they make an appearance. The ` animation-timing-function` is used with CSS animations, and the `transition-timing-function` is used with CSS transitions. Let's quickly look at how these timing functions survive in their respective habitats. ### Easing Functions in Animations In a CSS animation, the ` animation-timing-function` property can be defined in two places. It can be defined as part of the animation declaration: ``` /* 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; } ``` It can also be declared on each individual keyframe: ``` @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 your timing function as part of the animation declaration, what it really means is that each of your keyframes will actually be affected by that timing function value. It is no different than specifying the `animation-timing-function` on each keyframe individually, but you do save a few characters of typing. By way of cascading, a timing function declared on a keyframe will override any timing function specified on the animation declaration as well. 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 your animation reaches the next keyframe. This means you can't have an ` animation-timing-function` declared because there is no "next keyframe". ### Easing Functions in Transitions Transitions are a bit easier to look at since your `transition-timing-function` property can only live as part of the transition declaration: ``` /* shorthand */ #bar { transition: transform .5s ease-in; } /* longhand */ #karmaKramer { transition-property: all; transition-duration: .5s; transition-timing-function: ease-in; transition-delay: .1s; } ``` To be fair, with a transition, there is nowhere else any transition property could live, so don't heap too much praise on it. #### Note - Default Timing Function Values Specifying a timing function as part of your animation or transition is optional. The reason is that every animation or transition you use has its timing-function property defined by default with a value of **ease**. ### Meet the Easing Functions / Timing Functions Now that you have an idea of how easing functions fit into the whole CSS world, let's actually look at the various easing functions themselves. The easing functions you can set for the `transition-timing-function` and `animation-timing-function` properties are: - ease - linear - ease-in - ease-out - ease-in-out - step-start - step-end - steps() - cubic-bezier() In the following sections, I will go through and very briefly explain more about each one. #### cubic-bezier() Let's start with the most general-purpose of the easing functions - the **cubic-bezier()** one. This function takes four numbers as its argument, and these numbers map to points P1 and P2 from your easing function curve: ![](https://www.kirupa.com/html5/images/cubic-bezier_points_values.png) The first two arguments are made up of the x and y positions of point P1. The second two arguments are made up of the x and y positions of point P2. Points P0 and P3 are ignored because they are always going to be the same. When you put those numbers in, your **cubic-bezier** easing function will look as follows: ``` .foo { transition: transform .5s cubic-bezier(.70, .35, .41, .78); } ``` Now, for all practical purposes, you do not want to be randomly entering values into your cubic-bezier function and testing to see if the final result is what you like. That is just an awful use of time. What you want to do is visit the handful of online resources that simplify this task immensely. My favorite of those online resources is Lea Verou's [ cubic-bezier generator](http://cubic-bezier.com/): ![](https://www.kirupa.com/html5/images/lea_verou_72.png) Her site allows you to do everything you need in order to end up with a usable easing function. You can play with the cubic bezier curves, preview what an animation using that easing function would look like, and easily get the values for your cubic-bezier function for use in your CSS. My next favorite site is by [Mark MacKay](http://duopixel.ca/) and his [ visualizations of CSS timing functions](http://cssglue.com/cubic): ![](https://www.kirupa.com/html5/images/experiments_easings.png) Between Lea and Mark's sites, you should never have to painfully try to fiddle with the cubic bezier point values outside of just entering them. #### The Other Easing Functions By knowing how to define the **cubic-bezier()** function, you can create any sort of ease imaginable. The only downside with this function is that you have to specify the four values that make up the curve. The two web sites I posted certainly help with this, but so do the built-in easing functions you can specify such as **ease**, **linear**, **ease-in**, **ease-out**, and **ease-in-out**. These built-in functions are provided simply as a shortcut. You can re-create them by entering the correct point values into the cubic-bezier function. With that said, shortcuts are awesome. Here is what the cubic bezier curves for all of these would look like: ![](https://www.kirupa.com/html5/images/all_of_the_eases.png) In the above diagram, I gave our **ease** easing function some extra real estate both to make the layout work but also as a sign of respect because it is the default ease you get if you don't explicitly set your `transition-timing-function` and `animation-timing-function`. #### The step function The last thing we will look at is something that affects the rate at which your properties change but isn't an easing function. This non-easing function creature is known as a **step function**: ![](https://www.kirupa.com/html5/images/step_function_72.png) 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 you see above, your animated property ratio starts at 0%. At the 50% mark, it jumps to 50%. At the end of the animation, your property ratio reaches 100%. There is no smooth transition between the various frames or "steps". The end result is something a bit jagged. In CSS, the step function can be defined by using the appropriately named **steps** function: ```css .pictureContainer img { position: relative; top: 0px; transition: top 1s steps(2, start); } ``` The **steps** function takes two arguments: 1. Number of steps 1. A value of **start** or **end** 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: ```css .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. ## Further Reading Given the prevalence of easing in both traditional and computer generated animations, there is a lot of good stuff out there that you can read for more details. I've picked just a handful of my favorites: - [ W3C's Overview of Easing Functions](http://www.w3.org/TR/2013/WD-css3-transitions-20130212/#single-transition-timing-function) - [ CSS Easing Animation Tool](http://matthewlein.com/ceaser/) - [ Easing Function Cheat Sheet](http://easings.net/) - [ Robert Penner's Chapter on Tweening and Easing](http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf) - [ jQuery Easing Library](https://github.com/danro/jquery-easing/blob/master/jquery.easing.js)