Cubic Bezier Generator
Design a custom CSS easing curve by dragging control points, with a live preview and the common presets — plus what makes an easing curve feel natural.
The four numbers are not time and progress
cubic-bezier(x1, y1, x2, y2) draws a curve from (0,0) to (1,1) using those two
control points. Both coordinates are functions of a hidden parameter — call it t — and
t is not the time. Given a moment in the animation, the browser has to solve
x(t) = that moment for t first, and only then read off y(t). There is no formula for it; it is
root-finding, on every frame.
The tempting shortcut is to skip the solving and feed the time straight in as t. It looks right — both run from 0 to 1, both start and finish exactly where they should. Measured against the correct answer, the worst error along each curve:
| Curve | Worst error | At |
|---|---|---|
ease | 28.7 percentage points | 40% of the way through |
ease-in | 23.0 percentage points | 68% of the way through |
ease-out | 23.0 percentage points | 32% of the way through |
ease-in-out | 2.9 percentage points | 71% of the way through |
linear | 9.6 percentage points | 79% of the way through |
The last row is the one worth staring at. CSS linear is
cubic-bezier(0, 0, 1, 1), and its x(t) is 3t² − 2t³, not t. Solve it properly and
it is exactly the identity, as the name promises. Take the shortcut and you get a visibly
curved animation out of the one easing everybody assumes is safe to hand-roll. There is no
curve where the shortcut is right, other than at the two endpoints — which is precisely why
the mistake survives a quick look.
And ease is far more lopsided than it looks
The CSS default is cubic-bezier(0.25, 0.1, 0.25, 1). Where it has actually got to,
over the course of an animation:
| Time elapsed | Distance covered | |
|---|---|---|
| 10% | 9.5% | |
| 25% | 40.9% | |
| 50% | 80.2% | |
| 75% | 96.0% | |
| 90% | 99.4% |
Halfway through the time, ease is 80% of
the way there — not 50%. The whole second half of the running time is spent covering the last
20% of the distance. That long tail is why it reads as
smooth, and it is also why an ease animation feels finished well before it is,
which matters if you are chaining one onto the end of another.
Control points outside 0–1 on the y axis are legal and give you overshoot — a springy curve reaches 110% before settling, and an anticipating one dips to -10% before starting. Outside 0–1 on the x axis is rejected, because time has to stay monotonic or the curve stops being a function of it at all.
How to use
- Drag the two control points to shape the curve.
- Watch the preview animation to judge the feel.
- Start from a preset if you are unsure.
- Copy the cubic-bezier value into your CSS.
Frequently asked questions
What does an easing curve control?
How a value progresses through an animation over time, not what it animates. The horizontal axis is time and the vertical is progress, so a steep section means fast movement and a shallow one means slow. A straight line is linear motion, which almost always looks mechanical.
Why does linear look wrong?
Because nothing in the physical world starts and stops instantly. Objects accelerate and decelerate, so motion that does not looks artificial even to viewers who cannot say why. Easing out — fast at first, settling gently — is the safest default for interface animation.
Which easing should I use for what?
Ease-out for things entering or responding to a click, since the immediate start feels responsive. Ease-in for things leaving, since the acceleration away reads as departure. Ease-in-out for movements between two on-screen positions. Avoid ease-in for anything the user just triggered — the slow start feels laggy.
Can the curve go outside 0 and 1?
Vertically yes, horizontally no. Control points may exceed the vertical range, which produces overshoot and a bouncy feel — useful for playful interfaces. Time cannot run backwards, so the horizontal coordinates are constrained to between 0 and 1.
How long should an animation be?
Usually between 150 and 400 milliseconds for interface transitions. Below about 100 it reads as instant, and above 500 it starts to feel sluggish and gets in the user's way. Larger movements can justify longer durations than small ones.
Should I respect a preference for reduced motion?
Yes. A prefers-reduced-motion media query lets people who experience discomfort or nausea from movement turn it off, and honouring it is a genuine accessibility requirement rather than a nicety. Reducing animation to a simple fade, or removing it, is the usual response.
🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.