When it comes to animations on the web, CSS is a consequential part of this process. Using CSS prevents us from using heavy GIFs or other media types, but how are we supposed to control the animation time in CSS? Is it possible to play my animation in linear time instead of exponential? You’ll find an answer to all of your questions, fasten your seatbelts, I’ll teach you about CSS timing functions in this article 🥳
Table of Contents
What is a Timing Function?
A timing function (animation-timing-function
in CSS) lets you change the animation speed curve. I can hear you asking “What the hell does it even mean?”, let me show you an example.

As you can see from the example, the timing function literally changes how objects behave through the animation process. You can reach the code of this animation through this link by the way. CSS timing functions are not just limited by these though, there’re more.
Since we know what a timing function is, let’s look at how can we use it in our code.
Adding CSS Timing Functions
First, we have to have a basic HTML and CSS code to start coding animations. For this example, I’ll simply use the source code of the example that I provided earlier. Let’s start with the HTML.
<body> <div class="container _1"> <div class="circle"></div> <span>Linear</span> </div> <div class="container _2"> <div class="circle"></div> <span>Ease-in</span> </div> <div class="container _3"> <div class="circle"></div> <span>Ease-out</span> </div> <div class="container _4"> <div class="circle"></div> <span>Ease-in-out</span> </div> </body>
As you can see, there’re 4 containers that contain a div which has a class named circle in it. We’ll style this simple HTML code now but gotta leave CSS timing functions to last. Because before CSS timing functions, we still have to do basic styling.
body { background: gold; overflow: none; } .container { width: 100%; margin-bottom: 4px; position: relative; border-bottom: 1px solid rgba(255,255,255,0.7); .circle { z-index: 1; position: relative; left: calc(100% - 100px); border-radius: 50%; background: white; width: 95px; aspect-ratio: 1; box-shadow: inset 0px 0px 39px 16px rgba(0,0,0,0.24); } span { opacity: 0.5; z-index: 0; position: absolute; top: 50%; transform: translateY(-50%); font-family: sans-serif; font-size: 20px; display: block; width: 100%; text-align: center; } }
For those who don’t know, this is not pure CSS, it’s SCSS which is a CSS preprocessor. It improves the code readability so I’ve chosen to use it for this example. The CSS code simply makes the background orange, creates circles and aligns them to the right, and makes texts centered. It looks like this:

Now we have to add animations as well as the basic styling. For those who don’t know, the animations in CSS are defined with @keyframes
keyword. You can learn more about it from W3C animation docs. Let’s update our CSS code:
body { background: gold; overflow: none; } .container { width: 100%; margin-bottom: 4px; position: relative; border-bottom: 1px solid rgba(255,255,255,0.7); .circle { z-index: 1; position: relative; left: calc(100% - 100px); animation-name: to-right; animation-duration: 4s; border-radius: 50%; background: white; width: 95px; aspect-ratio: 1; box-shadow: inset 0px 0px 39px 16px rgba(0,0,0,0.24); } span { opacity: 0.5; z-index: 0; position: absolute; top: 50%; transform: translateY(-50%); font-family: sans-serif; font-size: 20px; display: block; width: 100%; text-align: center; } &._1 .circle { animation-timing-function: linear; } &._2 .circle { animation-timing-function: ease-in; } &._3 .circle { animation-timing-function: ease-out; } &._4 .circle { animation-timing-function: ease-in-out; } } @keyframes to-right { from { left: 0; } to { left: calc(100% - 100px); } }
We implemented the code that will make circles go to the right. However, we just used 4 timing methods, these were: linear
, ease-in
, ease-out
, and ease-in-out
. Aren’t there more? Or can we create our own timing functions? The answer is yes. Let’s look at the predefined timing functions first then I’ll teach you about bezier curves.
All the Timing Functions Defined in CSS
- linear: The
linear
timing function provides a constant speed throughout the animation or transition. It moves the element at a steady rate without any acceleration or deceleration. - ease:
ease
is the default timing function used if none is specified. It starts slowly, accelerates through the middle part of the animation, and then slows down towards the end. It’s a combination of ease-in and ease-out. - ease-in: The
ease-in
timing function starts the animation slowly and then accelerates as it progresses. The initial movement is gradual, and it gains speed towards the end. - ease-out:
ease-out
is the opposite ofease-in
. It starts the animation quickly and then decelerates as it approaches the end. The movement is fast initially and gradually slows down. - ease-in-out: The
ease-in-out
timing function combines the characteristics of bothease-in
andease-out
. It starts slowly, accelerates in the middle, and then slows down again towards the end. - step-start: The
step-start
timing function produces an animation that jumps immediately to the target value at the beginning and then maintains that value throughout the rest of the animation. - step-end:
step-end
is the opposite ofstep-start
. It maintains the initial value throughout most of the animation and then jumps to the target value at the end. - steps(): The
steps()
timing function allows you to create an animation that jumps from one point to another in a specified number of steps. For example,steps(4)
divides the animation into 4 equal steps, producing a discrete, frame-by-frame appearance. - cubic-bezier(): The
cubic-bezier()
timing function provides custom control over the animation’s acceleration curve using cubic Bézier curves. It takes four values (P1x, P1y, P2x, P2y), each ranging from 0 to 1, which define the points of the curve.
Creating your Own Timing Function with Cubic Bezier
If none of these timing functions fulfill your satisfaction, you can always create your own timing function using Cubic Beziers. In addition, you don’t have to deal with numbers and complicated math stuff because Chrome Dev Tools let you play around with the values dynamically.
Besides, you can also create a cubic bezier dynamically through online services that are built for developers for you and me. For instance, this website is very handy to create cubic beziers visually.
In addition, all of the timing functions are available for usage in modern Browsers. So you can use them freely.
Thank you for reading, I hope I was able to teach you timing functions in CSS, happy coding!
1 thought on “A Comprehensive Guide to CSS Timing Functions”