What is cubic-bezier in CSS?
It is a CSS timing function that controls how an animation accelerates and decelerates between keyframes.
Free, local and no login
Stop trial-and-error tuning of CSS easing values. Drag bezier handles, preview the movement in context and export the exact cubic-bezier timing function.
Create an animationNothing to install and nothing to open — this is the editor from the studio.
Drag the handles, or start from a preset. The dot replays the motion on every change, so you are judging the movement rather than the numbers.
animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);Paste it onto any animation or transition.
A working example with the exact code it produces. Copy it, or open it in the editor and change anything.
.elastic-in {
transform: translate3d(180px, 100px, 0);
width: 120px;
height: 120px;
background: #6366f1;
border-radius: 20px;
animation: elastic-in-anim 1000ms linear 0ms infinite both;
will-change: transform, opacity;
}
@keyframes elastic-in-anim {
0% {
transform: translate3d(180px, 100px, 0) scale(0.2, 0.2);
opacity: 0;
animation-timing-function: ease-out;
}
2.5% {
transform: translate3d(180px, 100px, 0) scale(0.417, 0.417);
opacity: 0.161;
}
5% {
transform: translate3d(180px, 100px, 0) scale(0.717, 0.717);
opacity: 0.308;
}
7.5% {
transform: translate3d(180px, 100px, 0);
opacity: 0.445;
}
10% {
transform: translate3d(180px, 100px, 0) scale(1.2, 1.2);
opacity: 0.571;
}
12.5% {
transform: translate3d(180px, 100px, 0) scale(1.291, 1.291);
opacity: 0.685;
}
15% {
transform: translate3d(180px, 100px, 0) scale(1.283, 1.283);
opacity: 0.785;
}
17.5% {
transform: translate3d(180px, 100px, 0) scale(1.206, 1.206);
opacity: 0.87;
}
20% {
transform: translate3d(180px, 100px, 0) scale(1.1, 1.1);
opacity: 0.938;
}
22.5% {
transform: translate3d(180px, 100px, 0);
opacity: 0.983;
}
25% {
transform: translate3d(180px, 100px, 0) scale(0.929, 0.929);
opacity: 1;
}
27.5% {
transform: translate3d(180px, 100px, 0) scale(0.897, 0.897);
opacity: 1;
}
30% {
transform: translate3d(180px, 100px, 0) scale(0.9, 0.9);
opacity: 1;
}
32.5% {
transform: translate3d(180px, 100px, 0) scale(0.927, 0.927);
opacity: 1;
}
35% {
transform: translate3d(180px, 100px, 0) scale(0.965, 0.965);
opacity: 1;
}
37.5% {
transform: translate3d(180px, 100px, 0);
opacity: 1;
}
40% {
transform: translate3d(180px, 100px, 0) scale(1.025, 1.025);
opacity: 1;
}
42.5% {
transform: translate3d(180px, 100px, 0) scale(1.036, 1.036);
opacity: 1;
}
45% {
transform: translate3d(180px, 100px, 0) scale(1.035, 1.035);
opacity: 1;
}
47.5% {
transform: translate3d(180px, 100px, 0) scale(1.026, 1.026);
opacity: 1;
}
50% {
transform: translate3d(180px, 100px, 0) scale(1.012, 1.012);
opacity: 1;
}
52.5% {
transform: translate3d(180px, 100px, 0);
opacity: 1;
}
55% {
transform: translate3d(180px, 100px, 0) scale(0.991, 0.991);
opacity: 1;
}
57.5% {
transform: translate3d(180px, 100px, 0) scale(0.987, 0.987);
opacity: 1;
}
60% {
transform: translate3d(180px, 100px, 0) scale(0.988, 0.988);
opacity: 1;
}
62.5% {
transform: translate3d(180px, 100px, 0) scale(0.991, 0.991);
opacity: 1;
}
65% {
transform: translate3d(180px, 100px, 0) scale(0.996, 0.996);
opacity: 1;
}
67.5% {
transform: translate3d(180px, 100px, 0);
opacity: 1;
}
70% {
transform: translate3d(180px, 100px, 0) scale(1.003, 1.003);
opacity: 1;
}
72.5% {
transform: translate3d(180px, 100px, 0) scale(1.005, 1.005);
opacity: 1;
}
75% {
transform: translate3d(180px, 100px, 0) scale(1.004, 1.004);
opacity: 1;
}
77.5% {
transform: translate3d(180px, 100px, 0) scale(1.003, 1.003);
opacity: 1;
}
80% {
transform: translate3d(180px, 100px, 0) scale(1.002, 1.002);
opacity: 1;
}
82.5% {
transform: translate3d(180px, 100px, 0);
opacity: 1;
}
85% {
transform: translate3d(180px, 100px, 0) scale(0.999, 0.999);
opacity: 1;
}
87.5% {
transform: translate3d(180px, 100px, 0) scale(0.998, 0.998);
opacity: 1;
}
90% {
transform: translate3d(180px, 100px, 0) scale(0.998, 0.998);
opacity: 1;
}
92.5% {
transform: translate3d(180px, 100px, 0) scale(0.999, 0.999);
opacity: 1;
}
95% {
transform: translate3d(180px, 100px, 0) scale(0.999, 0.999);
opacity: 1;
}
97.5% {
transform: translate3d(180px, 100px, 0);
opacity: 1;
}
100% {
transform: translate3d(180px, 100px, 0);
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.elastic-in {
animation: none;
transition: none;
}
}Same principle as the bounce: the oscillation is baked into keyframes rather than expressed as an easing function. Use it sparingly — elastic motion draws a lot of attention, which is the point once per screen and a nuisance twice.
Create custom CSS timing functions visually
Compare smooth, sharp and expressive motion curves
Use easing consistently across a complete animation
Open the curve editor in MotionCraft.
Drag the bezier control points while previewing motion.
Copy the cubic-bezier value or export the full animation.
It is a CSS timing function that controls how an animation accelerates and decelerates between keyframes.
Yes. MotionCraft can sample spring and bounce motion into CSS keyframes when a single timing function is not enough.