CSS UTILITY

CSS Cubic Bezier Editor

Design custom CSS timing functions with an interactive cubic-bezier curve editor. Visualize the easing curve, preview the animation, and copy production-ready code.

0.25
0.10
0.25
1.00

Animation Preview

Generated CSS
/* Timing function */
transition-timing-function: cubic-bezier(0.25, 0.10, 0.25, 1.00);

/* Full shorthand */
transition: all 0.3s cubic-bezier(0.25, 0.10, 0.25, 1.00);

The Mathematics of Motion

How Bezier Curves Work

A cubic Bezier curve is defined by four points: P0 (0,0), P1, P2, and P3 (1,1). P0 and P3 are fixed — the animation starts at 0% progress and ends at 100%. You control P1 and P2. The X axis represents time (0 to 1) and the Y axis represents progress (0 to 1, but can overshoot). The curve is calculated using the parametric equation: B(t) = (1-t)³P0 + 3(1-t)²tP1 + 3(1-t)t²P2 + t³P3. A steep curve means rapid change; a flat curve means slow change. The steepness at any point is the animation's velocity at that moment.

The Built-in Presets Decoded

ease         = cubic-bezier(0.25, 0.1, 0.25, 1.0)
ease-in      = cubic-bezier(0.42, 0, 1.0, 1.0)
ease-out     = cubic-bezier(0, 0, 0.58, 1.0)
ease-in-out  = cubic-bezier(0.42, 0, 0.58, 1.0)
linear       = cubic-bezier(0, 0, 1.0, 1.0)

The default CSS easeis not symmetrical — it accelerates quickly and decelerates slowly, making it feel natural for most UI animations. ease-out (fast start, slow end) is best for elements entering the viewport because they arrive quickly and settle gently. ease-in(slow start, fast end) works for exits because the element picks up speed as it leaves, getting out of the user's way.

Overshoot & Bounce Effects

P1 and P2's Y values can exceed the 0-1 range, creating overshoot. A Y value of 1.4 means the animation goes 40% past its target before settling back. cubic-bezier(0.34, 1.56, 0.64, 1)creates a playful spring-like overshoot — the element jumps past its final position and bounces back. For a more physical spring simulation, use cubic-bezier(0.68, -0.55, 0.265, 1.55)which overshoots on both the start (negative Y on P1 = initial pull-back) and end (Y > 1 on P2 = overshoot). X values, however, must stay between 0 and 1 because time cannot run backward.

Beyond Cubic Bezier: linear() Easing

CSS now supports the linear() easing function (Chrome 113+, Firefox 112+, Safari 17.2+) which accepts an arbitrary list of progress points. This enables effects impossible with cubic-bezier: true multi-bounce springs, elastic oscillations, and staircase stepping. For example, a 3-bounce spring: linear(0, 0.22, 0.68, 1.12, 0.98, 1.04, 0.99, 1). Tools like Jake Archibald's linear() generator can convert any JavaScript easing function into the CSS linear() format with configurable precision.

Frequently Asked Questions

Why does ease-out feel “snappier” than ease-in even at the same duration?

Humans perceive motion as responsive when it starts quickly. ease-out covers most of the distance in the first 30% of the duration, so the element appears to react immediately. ease-in is slow to start, creating a perceived lag even though the total time is identical. Research in UI animation suggests ease-out feels approximately 40% faster to users than ease-in at the same actual duration.

Can I apply different easing to different properties in the same transition?

Yes. Instead of the shorthand, declare each property separately: transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease. The transform gets a bouncy overshoot while opacity fades linearly. This technique is common for modal appearances: the modal slides in with spring easing but fades in smoothly.

How does animation-timing-function work with @keyframes?

The easing applies to each segment between keyframes independently, not to the entire animation. In @keyframes { 0% {} 50% {} 100% {} }, the easing curve is applied once from 0% to 50%, then reset and applied again from 50% to 100%. To apply different easings per segment, set animation-timing-function inside each keyframe rule.