As someone who’s created countless CSS animations, one thing I’ve always missed is elastic ease for keyframes
and transition
. Yes, you can use JavaScript libraries and other trickery (which we’ll get to in a moment), but, being the purest that I am, I’ve dove into the subject, checked out current solutions, learned the math behind it all, and built a CSS elastic ease generator that outputs a pure, clean, and accurate CSS animation code.
First, let’s try to better understand the elastic ease motion of an object. Let’s look at a red ball moving from point A to point B:
The ball starts at point A, moving toward its destination to point B, but it overshoots point B by some margin, effectively moving away from it. Then, it starts to slow down, stops, and starts moving in the other direction, back toward point B. It once again overshoots point B — this time by less margin — and continues repeating this pattern while decreasing the margin each time until it finally stops.
Here’s what elastic ease movement looks like on a graph.
If you’re using an animation library like GreenSock, just add ease:Elastic.easeOut
and keep on coding. It should be noted that while third-party solutions can help you overcome many hurdles, they do come with a price — sometimes literally — and they might affect your loading time, bundle size, and so on.
If you don’t want to (or can’t) use JS libraries, don’t worry, you can still implement an easing function with pure code. Yes, it requires more than one line of code, but it’s pretty simple, and I already did most of the work for you:
Elastic ease – #1: JS demo
No Description
What we have here is a simple elastic()
function that takes in a value between 0 and 1 (the dotValue
), and translates it to the correct X position (the elasticPosition
) of the dot. The function also takes in two constants: speed, which affects the duration of the animation, and the velocity of the movement. Feel free to play around with these numbers to see how they affect the dot’s movement.
When we click Run, the dotValue
resets to 0, and the function starts. It then runs constantly, using the requestAnimationFrame
function, increasing the value by speed
on each iteration and re-calculating the dot’s position for the new value. When the dotValue
gets to 1
, it stops.
As for the math, I must admit that my math skills are nowhere near good enough to properly explain what’s going on there, but I did check a few variations of this function from several different resources and ended up with this version, which is based on the math used by easings.net, plus some minor improvements.
In this example, I’ve used the setProperty
function that sets a CSS custom property that controls the left
position of the dot, but you can easily use it to control an element’s size, opacity, angle, color, and more. Just make sure that the input value is between 0 and 1, and that the two const
are properly defined according to your needs.
cubic-bezier
ease for single-step elasticityOne simple yet fantastic solution is to use cubic-bezier
ease to get a single-step elastic. You can do so by giving the fourth parameter of the function a high enough value so that the animation passes its destination, then return to its final value.
It’s not as rich as the other solutions, but it doesn’t use JS, it’s easy, and sometimes it’s all you need. I’ve created a few examples based on this method, and you can play around with cubic-bezier
to get the exact result you want using this great tool by Lea Verou.
Elastic ease – #2: cubic-bezier
No Description
Another way of achieving pure CSS elastic ease is to manually define each step of the movement with an animation keyframe to better understand this method. Let’s look at the movement on a graph one more time:
Here, you can see that the movement is divided into segments, which are separated by a vertical dashed line. Notice that the movement on each of these segments is just like the built-in CSS ease-in-out timing function that we all know, so we can translate each segment to a keyframe and get a fully elastic movement with pure CSS.
The problem with this method is that you first need to calculate each keyframe position and value, which is not an easy task. And, if you’re not accurate, the result might look jittery and inconsistent. To solve this, I’ve built a simple generator that creates the keyframes for you according to your parameters.
To allow for maximum versatility, we need to control three variables that, in turn, will control the trajectory of the movement:
Let’s break this down. We’ll start with the number of steps (segments) the animation has and the deceleration between them. This is important because each step will be later translated into a keyframe, and the size of each step will determine the keyframe position.
Elastic ease – #3: Steps
No Description
If you move the Steps slider, you control the number of segments that the movement will be built from. The Deceleration bar sets the size relation. When the slider is all the way to the left, all the segments will be the same size. If the slider is positioned to the far right, each segment will be half the size of the previous one. Note that if you use too many steps with a high deceleration value, the last few steps may be too small to have any effect.
Now that we have positions of the keyframes, let’s talk about the values. We’ll say that the initial value will always be 0, and the end value will always be 1. This way, we can later map these values to any CSS properties, and the velocity level will determine how much each step will deviate from the end value.
Elastic ease – #4: Velocity
No Description
Now that we have a nice elastic graph, the last step we have to complete is to add a duration slider that sets the overall time of the animation, then decide what we want to animate.
In this generator, I’ve added options to animate some commonly used properties, like width
, height
, and transform
, but you can easily adjust it to animate pretty much any property you need.
CSS Elastic ease generator
No Description
Now, open the generator on a full screen. Use the generator’s inputs to control the movement as you please, copy the output code, and use it in your project to add elasticity to your animations.
You can edit and change the animation for your needs. For example, you can drop animation-fill-mode
and add animation-iteration-count: infinite;
if you want your animation to loop. Or, you can add animation-direction: alternate;
, animation-delay
, and even combine two animations for different properties.
Here’s a cool example of animations that are using keyframes created by this generator:
Elastic ease – #5: Examples
No Description
I dream that one day CSS will have a built-in elastic function and that this generator will become useless. Think how nice it would be to have a simple elastic function that accepts these three arguments and produces a clean and beautiful elastic ease, like so:
.elasticObject { animation-name: goElastic; animation-duration: 1.5s; animation-timing-function: elastic(7, 1.9, 0.5); }
Until then, feel free to use this generator for anything you need, and if you have any thoughts or suggestions about how to improve this method, write them in the comments. Thanks!
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.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. 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 — start monitoring for free.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowThe useReducer React Hook is a good alternative to tools like Redux, Recoil, or MobX.
Node.js v22.5.0 introduced a native SQLite module, which is is similar to what other JavaScript runtimes like Deno and Bun already have.
Understanding and supporting pinch, text, and browser zoom significantly enhances the user experience. Let’s explore a few ways to do so.
Playwright is a popular framework for automating and testing web applications across multiple browsers in JavaScript, Python, Java, and C#. […]