Lin­ear() Is Not (That) Linear

My gut feeling tells me that not that many people have yet heard of or used the linear() easing function, one of the most exciting newer additions to CSS. Looking at the stats in the State of CSS survey, this is somewhat confirmed: only about 30 percent of respondents have used it and another 30 percent have never even heard of it. But what’s also interesting is the ratio of people who report to have heard of it but obviously never tried it then: 38 %. So either, a lot of people don’t have a use case for this feature, or they don’t really know what it can do. And, looking at the comments, something else might be a factor as well: maybe a few people don’t know that linear() is not linear, or what actually the (exhilarating) difference between the two is. One of the comments read, for example: “Never had a need for these easings, as it almost always feels unnatural. But again, great to have it!”

And I have to admit that this was my first reaction, too, when I heard about linear() for the first time: does it mean I can animate something just with a straight line? We already have the linear keyword. Where’s the difference?

The difference is that linear() doesn’t just interpolate linearly between 0 and 1, it defines a piecewise linear easing curve, meaning you can create custom transitions made up of multiple straight-line segments. So instead of defining the type of curve between two points, you can specify several points – or stops – in a comma-separated list to precisely control the speed changes during your animation. And this allows you to create – or approximate – quite complex animation curves in CSS with linear().

Let’s take this example:

animation-timing-function: linear(0, 0.25, 1);

Here, each decimal defines a stop. And by default, those stops have the same timing distance. So, the animation starts at 0, reaches 0.25 after the first half of the duration, and ends at 1 after the second half.

We can also change the timing distances by adding percentages after each of the points for finer control:

animation-timing-function: linear(0, 0.25 75%, 1)

So now, the animation progresses the first 25 percent of the change during the first 75 % of the animation. And the rest of the change happens during the last 25 % of the time.

Where it gets really interesting is when we use a lot more points, because this now allows us to approximate completely individual curves that are not possible with other timing functions like cubic-bezier().

Take a look at this bounce curve, for example:

Bounce smooth

This can be approximated with something like this:

Bounce approx

Which is a set of points that looks like this in a linear() function:

linear(0, 0.237 19.2%, 0.99 33.2%, 0.378 46%, 0.989 57.6%, 0.619 65.6%, 0.992 74.4%, 0.814 80.4%, 0.995 88%, 0.953 92%, 1)

Even with only this relatively small number of points, this animation already looks like a nice bounce:

CodePen: https://codepen.io/matthiasott/pen/YPwLMBV?editors=1100

And by increasing the number of points, we can approximate an even smoother curve, so that it is impossible to tell that our animation curve is actually made up of linear segments.

linear(0, 0.022 4.1%, 0.04 7%, 0.061 9.5%, 0.083 11.6%, 0.113 13.7%, 0.147 15.6%, 0.187 17.4%, 0.234 19.1%, 0.29 20.8%, 0.355 22.5%, 0.427 24.1%, 0.513 25.8%, 0.715 29.2%, 0.998 33.3%, 0.683 37.9%, 0.517 40.8%, 0.456 42.2%, 0.414 43.5%, 0.388 44.8%, 0.38 45.5%, 0.378 46.1%, 0.381 46.8%, 0.388 47.4%, 0.413 48.6%, 0.453 49.8%, 0.514 51.1%, 0.584 52.3%, 0.68 53.7%, 0.997 57.7%, 0.81 60.3%, 0.707 62.1%, 0.669 63%, 0.641 63.9%, 0.625 64.8%, 0.621 65.2%, 0.619 65.7%, 0.623 66.5%, 0.638 67.4%, 0.664 68.3%, 0.698 69.2%, 0.789 71%, 0.998 74.5%, 0.909 76.3%, 0.856 77.7%, 0.837 78.4%, 0.824 79.1%, 0.817 79.7%, 0.814 80.4%, 0.816 81%, 0.822 81.6%, 0.847 83%, 1 88.2%, 0.978 89.2%, 0.965 90.1%, 0.956 91%, 0.953 92%, 0.955 92.8%, 0.959 93.6%, 0.986 96.5%, 0.994 97.6%, 0.999 98.7%, 1)

The animation will look and feel super smooth.

CodePen: https://codepen.io/matthiasott/pen/wBMXgrK??editors=1100

But this is where you might – rightfully – object that editing something like this is almost impossible to do for our human brains. You might have a rough guess how a curve might look like but fine-tuning an animation just by editing the points? That seems completely impractical.

Luckily, there are a few tools that help you define your own easing curves with linear() or also come with a few useful presets that you can adjust to your liking.

One of them is Jake Archibald fantastic linear easing generator. You can pick one of the presets like Spring, Bounce, or Elastic and adjust the number of points and their decimal places. But you can also provide your own JavaScript or SVG easing curves and the easing generator will approximate it. You could, for example, head over to the infamous easings.net, pick an easing curve like easeOutBounce and throw it into the generator. Or also come up with your own logic for the timing of the animation.

Linear easing generator screenshot

Another great tool is the Easing Wizard by Matthias Martin, also because of its – wait for it – ease of use and the many presets like Bounce, Wiggle, or Overshoot animation timing functions. Firm, soft, sharp, subtle, playful, springy – just pick your favourite and adjust it a bit, then copy the linear() function to the clipboard.

Easing wizard screenshot

As of today, linear() is a baseline feature supported in all modern browsers since 2023. You can always use it with a fallback, for example by using @supports, and it has the potential to make all your animations so much better.

Further Reading

This is post 21 of Blogtober 2025.

~

21 Webmentions

11 Likes

7 Reposts

ⓘ Webmentions are a way to notify other websites when you link to them, and to receive notifications when others link to you. Learn more about Webmentions.