This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →Cubic Bezier Generator
Web & MarkupDrag a cubic-bezier curve, read the CSS, Tailwind or linear() straight off it, and pick from the 30 Penner presets with their measured fit error attached.
Sampled values
| Input progress | Output progress |
|---|---|
| 0% | 0.0000 |
| 10% | 0.0948 |
| 20% | 0.2952 |
| 30% | 0.5133 |
| 40% | 0.6825 |
| 50% | 0.8024 |
| 60% | 0.8852 |
| 70% | 0.9408 |
| 80% | 0.9756 |
| 90% | 0.9943 |
| 100% | 1.0000 |
Show acceleration
Presets
Preview & compare
A wiggle ends where it started: the "to" value above is the amplitude, and the compare lane is hidden because there's no fixed end value to race it against.
transition-timing-function: ease;
No network activity while you use this tool Show the numbers
- Requests to any other server
- 0
- Requests since you started typing
- —
- Same-origin requests
- 0
Counted live by your browser's own Performance Timeline — the same data the DevTools Network panel reads. It cannot see what a browser extension does, and it is not meant to replace checking for yourself: here is how, in thirty seconds .
What the curve is hiding: speed
A CSS cubic-bezier() is usually drawn as a position curve — where the animated
value is at each moment — because that is the easy picture to draw. What it actually encodes
is a speed profile: how fast the property moves at every instant, which is the
derivative of the curve everyone draws instead. ease-in
(cubic-bezier(0.42, 0, 1, 1)) starts at rest, accelerates the whole way, and
arrives at roughly 1.72 times its average speed — then the animation simply ends, with no
deceleration at all. That hard stop is the "why does this feel wrong on an entrance" everyone
has felt and few have had a number for.
Every easing function as a cubic-bezier, and how close it gets
Robert Penner's 30 easing equations (Sine, Quad, Cubic, Quart, Quint, Expo, Circ, Back,
Elastic and Bounce, each as In, Out and In-Out) predate CSS's cubic-bezier() and
most of them are not exactly reproducible by one — a cubic-bezier's output is a cubic
polynomial in its parameter, so it can reverse direction at most twice, while Elastic and
Bounce reverse many more times than that. easings.net publishes a close
cubic-bezier approximation for the 24 curves that do reduce reasonably well, but
does not say how close. This page measures it: every Penner preset chip above carries the
maximum error of its published fit against the exact function, sampled densely and re-checked
by an independent transcription of Penner's own 2001 equations.
Frames, not curves
A browser never renders a continuous curve — it samples your easing once per repaint. At 60Hz, a 200ms transition gets about 12 rendered frames; the same transition at 120Hz gets about 24. A curve with a sharp knee near its fastest point can cover a large share of its total travel between two adjacent frames, and that share depends on the duration, the travel distance and the refresh rate together — not on the curve alone. That is why the exact same CSS can look smooth on a fast display and slightly stepped on a 60Hz one, and it is a sampling fact, not a bug in the easing.
linear() explained by its error
CSS's linear() function draws a piecewise-linear approximation of any curve from
a list of value/percentage stops, which is how a spring, a bounce or any curve a cubic-bezier
cannot represent still ships as a single easing value. The right number of stops is not a
round number picked in advance — it is however many points keep the approximation within a
stated pixel error on the distance actually being animated, since the same fractional error
is 1px on a 200px slide and 10px on a 2000px one. linear() shipped in Chrome 113,
Safari 17.2 and Firefox 112; the @keyframes fallback this page also offers covers
the gap for anything earlier.
How to do this in code
The Web Animations API's element.animate() accepts the identical
easing string as the CSS property — a cubic-bezier(),
linear() or a keyword. Motion (formerly Framer Motion) accepts a
cubic-bezier array or a named ease in its transition prop but not
raw linear(); GSAP has its own CustomEase plugin and does not read
CSS easing strings directly. Check which oracle a library actually uses before assuming a
value copied from here behaves identically elsewhere.
Frequently asked questions
- Why does ease-in feel wrong on things entering the screen?
- ease-in (cubic-bezier(0.42, 0, 1, 1)) starts at rest and arrives at 1.72 times the average speed, then stops dead the instant the animation ends — there's no deceleration into the resting position. For something entering the screen, the eye expects to see it settle, not slam to a halt at full speed. ease-out does the opposite (starts fast, eases into rest), which is why it's the usual choice for entrances and ease-in for exits.
- What do the four numbers in cubic-bezier() mean, and why can't x go outside 0-1?
- cubic-bezier(x1, y1, x2, y2) places two control points, P1 = (x1, y1) and P2 = (x2, y2), between the curve's fixed start (0, 0) and end (1, 1). x is input progress (time through the animation) and y is output progress (how far the animated property has moved). x1 and x2 must stay between 0 and 1 because x represents time — a control point outside that range would make the curve run backwards in time, which the spec (and every browser) rejects. y1 and y2 have no such limit: a y past 1 or below 0 is exactly what makes a curve overshoot or dip backwards, like the Back family below.
- How do I make a spring or bounce in plain CSS?
- Neither a spring nor a bounce is a cubic-bezier — a cubic only reverses direction at most twice, and a real spring or multi-bounce keeps oscillating. The honest way to ship one in CSS is the linear() function: sample the physics curve finely, keep only the points that matter, and list them as linear(v1 p1%, v2 p2%, ...). That output is on this page's plan for the Spring and Bounce modes; today the page's linear() tab already works for any Bézier curve too, for engines that only accept one function name.
- How many points does a linear() need?
- As many as it takes to stay under a stated pixel error on the travel you actually animate — not a fixed number. A 0.5px tolerance on a 200px slide needs fewer points than the same tolerance on a 2000px one, because the same fractional error covers more physical distance. This page derives the point count from the tolerance and the travel, then re-parses the rounded string it just emitted and measures the real error against the true curve, rather than picking a round number and hoping.
- Can I convert a spring to a cubic-bezier?
- Sometimes, and only approximately. A cubic-bezier's y is a cubic polynomial in t, whose derivative is a quadratic — so it can change direction at most twice inside the curve. A gentle, single-overshoot spring fits reasonably well; a spring with several visible bounces reverses direction more than twice and has no honest cubic-bezier fit at all. Where a fit exists, the right way to use it is with its measured error attached, never as an exact replacement.
- What's the difference between ease and ease-in-out?
- ease (cubic-bezier(0.25, 0.1, 0.25, 1)) is asymmetric: it starts gently, but its fastest point is close to the beginning and it arrives at a dead stop. ease-in-out (cubic-bezier(0.42, 0, 0.58, 1)) is symmetric around the midpoint — equally slow at both ends, fastest in the middle. ease is CSS's own default and the more common choice; ease-in-out reads as more deliberate and is common for modal or panel transitions where both edges should feel equally soft.
- Why does my animation look choppy on some monitors and fine on mine?
- A curve is smooth in the abstract, but a browser only ever paints it at your display's refresh rate — a 200ms animation gets 12 rendered frames at 60Hz and 24 at 120Hz. A curve with a sharp knee near its peak speed can cover a large fraction of its travel in a single frame at 60Hz and look fine at 120Hz purely because there are twice as many samples to smooth the same motion. It's a sampling fact about the curve, the duration and the display together, not a property of the curve alone.
- Is my easing sent anywhere?
- No. Every curve on this page — dragged, typed or pasted — is computed and drawn entirely in your browser. There is no server this tool sends your input to.
Explore more tools
Build linear, radial and conic CSS gradients, and see the same stops fade through grey in sRGB or stay vivid in OKLCH.
Minify CSS without losing nested rules, custom properties or browser hacks.
Turn one seed color into a 50–950 tint/shade ramp with even OKLCH steps, an explicit chroma taper, and a contrast matrix.