[ANIMATION](https://www.kirupa.com/css_animations/index.htm) [BOOK](http://www.amazon.com/dp/1502548704?_encoding=UTF8&camp=15041&creative=373501&linkCode=as3&tag=kirupacom) # Working with CSS Timing (aka Easing) Functions by [kirupa](https://www.kirupa.com/me/index.htm) | 28 October 2016 So far, we've created animations and transitions by specifying some CSS properties, changing some property values, and setting a duration. We really haven't gone beyond the basics. We are going to change that starting with this tutorial. In this tutorial, we are going to learn about **timing functions** (often referred to also as **easing functions**) and the extremely super-important role they play in making our animations look more realistic. Onwards! ## What are Timing Functions? When creating animations, we know that property values change over a period of time. That is the textbook definition of an animation. How exactly the values change has a major impact on the animation that we end up seeing. For example, your property values could change linearly with time: ![](https://www.kirupa.com/html5/images/easing_linear_ease.png) This will result in you seeing something change at a constant speed...like a really badly designed robot. If you want your property values to change in a more realistic way, you could throw in a slight deceleration: ![](https://www.kirupa.com/html5/images/easing_out.png) In this case, your property value speeds up very quickly at the beginning and then slowly tapers off towards the end. To get a better understanding of how all of this impacts what we see, take a look at the following animation where we have a few circles that are sliding from left to right: While it may be hard to believe, the animation defined for these circles is mostly identical. They have the same starting point, ending point, and duration. If you pay really close attention you can see that all three circles start and end at the same time. The only thing that is different is how each of these circles gets from its starting position to its ending position. The only thing that is different is the speed at which the property values changed for each circle. There is a magical thing that is responsible for these speed variations that alter how properties animate from their initial value to their final value. **That magical thing is, as you may have guessed, the timing function**. The timing function isn't nearly as glamorous or exotic as I am making them out to be. It is just a mathematical expression made up of some weird looking numbers that ends up affecting how our property values change. Here is a sneak peek what a timing function actually looks like: ![](https://www.kirupa.com/html5/images/cubic-bezier_points_values.png) By the end of this tutorial, we will come to understand what all of that means. For now, let's take a quick detour and look at how timing functions can be specified in CSS. ## Timing Functions in CSS Despite how important timing functions are and how complex they might be under the hood, the way you can use them in CSS is extremely simple. 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 do that in the following sections. ### Easing Functions in 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. Below 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; } ``` 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 on your last keyframe because there is no "next keyframe". If you do end up declaring a timing function on the last 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. ### Easing Functions in 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 delcaration or as part of the `transition-timing-function` property in the longhand world. ``` /* shorthand */ #bar { transition: transform .5s ease-in; } /* longhand */ #karmaKramer { transition-property: all; transition-duration: .5s; transition-timing-function: ease-in; } ``` There really isn't anything more to say. As CSS properties go, transitions are pretty easy to deal with! #### 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**. ## Making Sense of Timing Functions In the previous sections, we took a birds-eye view of what timing functions are and how you can use them in CSS to bring your animations and transitions to life. What we've really done is just looked at the mechanical details. We barely scratched the surface of what timing functions are and how they will impact the property values they are designed to affect. That is...until now! ### Meet the Timing Function Curve When we talk about timing functions, we are often not talking about them in terms of their CSS names (ease, ease-in, etc.) Instead, timing functions are represented visually using something known as a **timing function curve**: ![](https://www.kirupa.com/html5/images/hand_drawn.png) 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, and knowing how to read it is important. The timing function curve helps us determine how a particular timing function will impact how property values change. #### The Example To help us make sense of timing curves, we are going to need a simple example. Our example is the following: we have an element whose `opacity` property value changes from 1 to 0 over a period of 2 seconds. To keep things simple, let's say that this change happens linearly. 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 our `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 Timing Functions Here is where things get interesting. Timing 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**. Our earlier chart where we plotted the opacity over a period of time isn't directly relevant to understanding timing function. To draw a chart through the eyes of a timing function, we are going to generalize things a bit and switch over to using percentages. Instead of plotting the property value over a period of time, we are going to 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 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 Timing Functions (Again!) This is far less dramatic than what this section heading may imply. The percentage-based graphs you saw in the previous section actually contain the timing 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 we've seen a few times already is the mythical timing function curve that represents the timing function. 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 timing 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 realistic 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 timing 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 timing 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**. For CSS animations, using timing functions in the shorthand and longhand variants of the `animation` property look as follows: For CSS transitions, the markup looks as follows: Let's put the carriage before the horse and meet the timing funtions first. They are: Here is the thing. What a timing function does is pretty simple. **It allows you to specify how our animated values change with time.** Do our values speed up as they change? Do they slow down? Do they have a slight bounce? Our timing function is responsible for answering questions like these and a whole lot more. Don't worry too much about Pretty cool, right? Now, we mentioned earlier that timing functions alter the speed at which properties change. That is their boring textbook definition. The more exciting thing to remember is that **timing functions help make your animations more realistic**. In real life, objects don't move at a constant speed. They have sudden jolts, they start suddenly before slowing down, they accelerate, they bounce in/bounce out, and so on. Objects in real life move in a variety of natural ways, and the closer we can mimic that natural behavior with our animations, the better our animations will be. At first glance, it may look like each circle is pretty different in how it moves around. Would you believe me if I told you that these three circles have the exact same duration and starting/ending property values for their position? Well, it is true! Their starting points and ending points are exactly the same and they reach those two points at exactly the same time. There is only one thing that differentiates the animation for these three circles. That one thing is the **rate at which the CSS property values change** - better known as a **timing function**! In this tutorial, we'll take a look at what timing functions are, how you can specify them in CSS, and learn about why they are one of the most important things you can specify when working with CSS animations and transitions. Onwards! happens to your animated properties while your animation is running is almost as important as where they end up. Take a look a the following example: You will see ## 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)