Skip to content

All tools (41)

JSON 6
Time & Date 4
Encoding & Decoding 4
Generators 3
Text & Data 4
Logs & Debugging 1
Config & Infra 3
Security & Hashing 4
Color & Design 5
Numbers & Bits 3
Web & Markup 4

Nothing leaves the cave.

Nothing you paste ever leaves your device. There is no server to send it to.

How you can check →
DevToolsCave

    This tool runs entirely in your browser. Nothing you paste is uploaded.

    How you can check →

    Cubic Bezier Generator

    Web & Markup

    Drag 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.

    The easing curve A cubic-bezier curve from control points (0.25, 0.10) to (0.25, 1.00). Drag a handle, or use the four numeric inputs, to change it. 0.0 0.5 1.0 0%25%50%75%100%
    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
    Velocity — multiples of average speed
    0.00.51.01.52.02.5
    Show acceleration
    Starts at 0.4× average speed, peaks at 2.3× at 21%, arrives at rest. Largest single-frame step at 300 ms on 60 Hz: 12.5% of the travel (38 px).
    assumed 60 Hz — not measured
    CSS value
    ease

    Presets

    Sine
    Quad
    Cubic
    Quart
    Quint
    Expo
    Circ
    Back
    Elastic
    In · no fit Out · no fit InOut · no fit
    Bounce
    In · no fit Out · no fit InOut · no fit

    Preview & compare

    Current
    Compare: linear
    transition-timing-function: ease;

    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.