Analytics cookies
We use optional Google Analytics to understand which tools are useful and improve the site. Analytics stays off unless you accept. Privacy Policy
Design cubic-bezier and spring easing curves, preview motion, and copy production-ready CSS.
Drag the handles or type values
Set the bounce below
Across: timeUp: eased progress
X runs from 0 to 1, as CSS requires. Y can go from −2 to 3 here; CSS allows any y. Arrow keys change a value by 0.01, Shift + arrow keys by 0.1.
At 0 the spring settles without overshooting. Higher values carry it past the end and back before it settles.
Same timing as the ease keyword.
cubic-bezier(0.25, 0.1, 0.25, 1).element {
transition: transform 600ms cubic-bezier(0.25, 0.1, 0.25, 1) 0ms;
}This visualizer is an editor for CSS cubic-bezier() easing curves and spring-style linear() curves. Shape a curve on the graph or with exact numbers, check its progress at any moment with the time slider, and watch it move, scale, fade or rotate a test object. Then copy the easing value or a ready-made transition.
Everything runs in your browser, and nothing is saved: reloading the page starts again from the default ease curve.
An easing curve maps elapsed time, on the horizontal axis, to eased progress, on the vertical axis. Both run from 0 to 1. The curve always starts at (0, 0) and ends at (1, 1); the two control points between them shape the acceleration. This is the tool’s default, the same curve as the ease keyword:
cubic-bezier(0.25, 0.1, 0.25, 1)0.25, 0.10.25, 1Halfway through the duration, this curve is already 80.2% of the way there. x1 and x2 must stay between 0 and 1, because time can only move forward; CSS rejects the whole value otherwise. y1 and y2 can go below 0 or above 1, which makes the motion overshoot its start or end.
Duration doesn’t change the shape. A 300 ms and a 1000 ms transition with the same curve pass through the same progress at the same share of their time; the longer one simply takes longer.
Spring mode models a spring that starts at rest and is pulled to its end value, stretched so it has settled by the end of the duration. Bounce sets how loosely it is damped. At 0 it settles without overshooting; higher values carry it past the end and back before it settles.
A spring curve can’t be written as cubic-bezier(), so the tool samples it at 41 evenly spaced moments and writes those values as a linear() easing function, which joins them with straight lines. The graph, the preview and the copied CSS all use the same points.
No curve suits everything, but these starting points work for most interfaces:
Timing matters as much as the curve. Small changes such as a button state or a tooltip usually feel right at 150 to 300 ms; larger movements can take a little longer. Try your choice at the real duration with Replay before you ship it.
Some people turn on a reduce-motion setting because movement on screen can cause discomfort or distraction. A good curve doesn’t change that. Use the prefers-reduced-motion media query to add movement only for people who haven’t asked for less:
@media (prefers-reduced-motion: no-preference) {
.element {
transition: transform 600ms cubic-bezier(0.25, 0.1, 0.25, 1) 0ms;
}
}This tool follows the same idea. Nothing moves when the page loads, the time slider lets you inspect a curve without any animation, and Replay only plays when you press it.
cubic-bezier() is a CSS easing function. It sets how a transition or animation’s progress is spread over its duration. Its four numbers place two control points that bend a curve running from (0, 0) to (1, 1). The keywords ease, ease-in, ease-out and ease-in-out are fixed cubic-bezier curves.
They are the coordinates of the two control points. x is elapsed time and y is progress, both as fractions of the whole. (x1, y1) shapes how the motion starts and (x2, y2) how it ends. The curve doesn’t pass through these points; it bends toward them, like the handles in a vector drawing app.
Yes. y1 and y2 can be below 0 or above 1, so progress can pass the end and come back, or pull back before it starts. A transform shows this as movement past the target. A property with fixed limits, such as opacity, stops at those limits, so its overshoot doesn’t show. x1 and x2 must stay between 0 and 1.
Duration is how long the change takes. Easing is how the progress is spread over that time. A longer or shorter duration stretches or squeezes the same curve without changing its shape: with ease, a 300 ms and a 1000 ms transition are both about 80% of the way there halfway through.
There’s no single best curve, but a common pattern works well: ease-out for things that appear or enter, ease-in for things that leave, and ease-in-out for things that move from one place to another. Linear suits continuous motion such as spinners. Keep overshoot for occasional emphasis, and keep small interface changes short, around 150 to 300 ms.
No. cubic-bezier() is plain CSS: use it in transition-timing-function, animation-timing-function, or the transition and animation shorthands. This tool uses JavaScript to draw and preview the curve, but the CSS it writes works on its own.
Some people set their device to reduce motion, because movement on screen can cause discomfort or distraction. The prefers-reduced-motion media query lets your CSS respect that: remove or shorten movement that is only decoration, or replace it with a simple fade. Motion that carries meaning, such as a progress indicator, can stay if it is gentle.