Easing Functions Explained: cubic-bezier in CSS and Motion
By Hizmedia · · 6 min read
An animation's easing decides how its speed changes over its duration. The same 300 milliseconds can feel sluggish, abrupt or effortless depending on the curve. In CSS and in Motion, most easing curves are cubic Béziers: four numbers that bend a line from start to finish. Pick a preset or drag the handles below to see how each shape moves.
Try it
/* CSS */
transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
// Motion
transition={{ duration: 1.1, ease: [0.22, 1, 0.36, 1] }}The curve plots progress (up) against time (across). Where it's steep, the ball moves fast; where it's flat, it's slow.
How cubic-bezier works
A cubic-bezier curve always starts at (0, 0) and ends at (1, 1): the start and the end of the animation. The four numbers you write are the two handles that bend it, cubic-bezier(x1, y1, x2, y2). The x values are time and must stay between 0 and 1. The y values are progress and can go outside that range, which is how a curve overshoots its target and comes back.
lineariscubic-bezier(0, 0, 1, 1): constant speed.ease(the CSS default) iscubic-bezier(0.25, 0.1, 0.25, 1).ease-iniscubic-bezier(0.42, 0, 1, 1): starts slow, ends fast.ease-outiscubic-bezier(0, 0, 0.58, 1): starts fast, ends slow.ease-in-outiscubic-bezier(0.42, 0, 0.58, 1): slow at both ends.
Which curve to use when
- Things arriving on screen (menus opening, toasts, page content): ease-out. They move fast at first and settle gently, which reads as responsive. Stronger curves such as
cubic-bezier(0.22, 1, 0.36, 1)feel more polished than the built-in keyword. - Things leaving: ease-in. They gather speed as they go, so the exit doesn't linger.
- Things moving from one place to another on screen: ease-in-out.
- Continuous motion, such as marquees, spinners and progress bars: linear, because any easing would make a loop pulse.
- A little playfulness: a back curve such as
cubic-bezier(0.34, 1.56, 0.64, 1)overshoots slightly before settling.
Most interface animations should be short: about 150 to 300 milliseconds for small elements and up to 500 for large panels. A good curve can't rescue an animation that's too long.
Easing in Motion
Motion takes the same four numbers as an array, or a named easing:
transition={{ duration: 0.35, ease: [0.22, 1, 0.36, 1] }}
transition={{ duration: 0.35, ease: "easeOut" }} // also "easeIn", "easeInOut", "circOut", "backOut", "anticipate"For anything that reacts to the pointer or can be interrupted, consider a spring instead of an easing curve: springs carry their velocity into the next movement, which curves can't.
Beyond cubic-bezier
A single cubic Bézier can't bounce more than once. For multi-bounce or stepped motion, CSS has the linear() function, which takes a list of points and draws straight lines between them, and steps() for frame-by-frame movement such as a ticking counter. Modern browsers support both.