Level up CSS transitions with cubic-bezier
If you’ve ever noticed that your CSS transitions feel a bit… flat, you’re not alone (I seem them a lot! 😭). The default ease timing function works fine, but it’s generic. Real-world motion has character, it bounces, overshoots and feels natural. That is what cubic-bezier is for.
What is cubic-bezier?
In CSS, cubic-bezier is used in the transition-timing-function or animation-timing-function property. It defines how intermediate values are calculated during a transition using a cubic Bézier curve (orly?! 🦉).
The syntax looks like this:
cubic-bezier(x1, y1, x2, y2)
Those four numbers define two control points on a curve. The curve starts at (0,0) and ends at (1,1), representing the beginning and end of the transition. The control points shape how the animation progresses between those states.
For a detailed explanation, check out the MDN Web Docs.
Examples that make a difference
Let’s look at some examples that use default easing functions and then show a more interesting timing functions. Hover to see the effects:
Before:
After taken from Perron’s docs; see logo:
This is how it is done with Tailwind CSS:
<div class="transition duration-500 ease-[cubic-bezier(0.68,-0.6,0.32,1.6)] hover:scale-80 hover:rotate-359"></div>
And how you write it with CSS:
.icon {
transition: transform 0.5s cubic-bezier(.68 -.6 .32 1.6);
}
.icon:hover {
transform: scale(0.8) rotate(359deg);
}
Before:
After:
This is how it is done with Tailwind CSS:
<div class="transition-transform duration-300 ease-[cubic-bezier(0.34,1.56,0.64,1)] hover:scale-150"></div>
And how you write it with CSS:
.button {
transition: transform 0.3s cubic-bezier(.34 1.56 .64 1);
}
.button:hover {
transform: scale(1.5);
}
Before:
After:
This is how it is done with Tailwind CSS:
<div class="transition-transform duration-500 ease-[cubic-bezier(0.87,0,0.13,1)] hover:translate-x-8"></div>
And how you write it with CSS:
.pill {
transition: transform 0.5s cubic-bezier(.87 0 .13 1);
}
.pill:hover {
transform: translateX(2rem);
}
Notice the negative values in the cubic-bezier functions? Those create the “bounce” effect that overshoots its target before settling into place and what gives that “premium” feel.
Tailwind CSS provides better defaults with
ease-{in,out,in-out}classes
Finding the perfect curve
Rather than guessing values, use Easing Wizard. It’s a beautiful, interactive tool (that I shared in my notes some weeks ago; only accessible via atom feed 🤫) where you can drag control points and see the resulting animation in real-time. Copy the generated cubic-bezier values directly into your CSS.
The difference between ease and a well-crafted cubic-bezier curve is immediately noticeable. Your interfaces will feel more responsive, more alive and more professional.
Try replacing your next transition: all 300s ease with transition: all 300s cubic-bezier(.68 -.6 .32 1.6) and see the difference for yourself.
Want to read me more?
-
Add a custom Tailwind CSS class for reusability and speed
Learn how to add a custom CSS class with Tailwind CSS' plugin system. -
Introducing Turbo Transition: create smoother Turbo Streams
New from Rails Designer: Turbo Transition. A “minion” for Turbo-Frames and Streams that transitions elements as they enter or leave the DOM. -
Smooth Transitions with Turbo Streams
Add custom behavior to `turbo:before-stream-render` listener to add smooth transitions to turbo stream when adding and removing elements.
Over to you…
What did you like about this article? Learned something knew? Found something is missing or even broken? 🫣 Let me (and others) know!
Comments are powered by Chirp Form
{{comment}}