Snappy button reaction
.btn { transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1);}.btn:hover { transform: translateY(-2px);}Most of the lift happens fast at the start, then settles - feels responsive to the cursor instead of sluggish.
Draw custom CSS easing curves with a live animation preview.
Last updated
.element {
transition: transform 1.2s cubic-bezier(0.25, 0.1, 0.25, 1);
}An *easing function* in CSS controls how an animation accelerates and decelerates over its duration. The keywords ease, ease-in, ease-out, and ease-in-out are shortcuts for four specific curves. For anything beyond those four, CSS gives you cubic-bezier() - a function that takes four numbers and draws a custom curve.
Those four numbers are the coordinates of two control points (x1, y1, x2, y2). They are awkward to write by hand because tiny changes have big visual effects, and small overshoots produce *bouncy* motion that you can't see in the numbers alone. A visual editor lets you drag the handles and watch the curve respond - much faster than tweaking decimals.
Coddy's editor draws the curve in real time, animates a preview ball using your easing, and provides presets covering common patterns: the CSS keywords, Material Design's standard curve, a bouncy out, and an anticipate-overshoot. Copy the resulting cubic-bezier() string and paste it into your CSS - runs entirely in your browser.
linear - equal progress per unit time.Click a preset that's close to the feeling you want. *Material standard* and *Bouncy out* are good starting points for UI motion; *ease-out* is the safe default for entry animations.
The teal handles are the two control points. Drag the first to tune how the animation *starts*; drag the second to tune how it *ends*. Pulling a handle above the top edge produces overshoot.
Choose a realistic duration for your real animation. UI transitions typically run 150–300ms; emphasis motions 400–600ms. Click *Replay* to re-trigger the preview at the new duration.
For precise values, type into the X1/Y1/X2/Y2 inputs underneath the curve. Y can go below 0 or above 1 - X is always 0..1.
Click *Copy* to get the full transition rule. Drop it into your stylesheet and replace transform with whatever property you're animating.
Common easings and the cubic-bezier values behind them. All four keywords below are aliases for specific cubic-bezier curves.
| Easing | cubic-bezier values | When to use |
|---|---|---|
ease | (0.25, 0.1, 0.25, 1) | Default for transition - gentle but generic |
linear | (0, 0, 1, 1) | Constant speed - usually wrong for UI, right for spinners |
ease-in | (0.42, 0, 1, 1) | Slow start, fast end - best for exits |
ease-out | (0, 0, 0.58, 1) | Fast start, slow end - best for entries and reactions |
ease-in-out | (0.42, 0, 0.58, 1) | Symmetric - best for back-and-forth toggles |
| Material standard | (0.4, 0, 0.2, 1) | Snappy modern UI motion |
| Bouncy out | (0.18, 0.89, 0.32, 1.28) | Overshoots and settles - playful entries |
.btn { transition: transform 180ms cubic-bezier(0.4, 0, 0.2, 1);}.btn:hover { transform: translateY(-2px);}Most of the lift happens fast at the start, then settles - feels responsive to the cursor instead of sluggish.
.card { transition: transform 350ms cubic-bezier(0.18, 0.89, 0.32, 1.28);}The Y2 value of 1.28 makes the curve overshoot the destination, then settle. Use sparingly - bouncy motion gets tiresome if everything moves this way.
.hero { transition: transform 500ms cubic-bezier(0.68, -0.55, 0.27, 1.55);}Negative Y1 means the animation briefly moves in the *opposite* direction before going to its destination. Borrowed from classic animation - a tiny anticipation makes the main move feel intentional.
ease-in for entry animations. It starts slow and ends fast - the opposite of what feels responsive. Use ease-out instead.linear for UI motion because it seems neutral. Constant-velocity motion looks mechanical; it is correct for progress bars and spinners but rarely for everything else.cubic-bezier() mean?cubic-bezier(x1, y1, x2, y2). The first point shapes how the animation *starts*, the second shapes how it *ends*. X is always between 0 and 1 (time); Y can go beyond 0..1 for overshoot/anticipate effects (progress).cubic-bezier(0.4, 0, 0.2, 1). For exits, *ease-in* is appropriate. Avoid *linear* unless you're animating progress.ease and ease-out?ease also starts gently. ease-out starts at full speed and decelerates - that *immediate* movement is why it feels more responsive than ease.cubic-bezier(0.18, 0.89, 0.32, 1.28) overshoots ~28% before settling. For multi-bounce motion you need @keyframes or a spring-physics library - cubic-bezier can only overshoot once.@keyframes animations?animation-timing-function, either on the animation shorthand or per keyframe. For complex multi-step motion, you can apply a different easing between each keyframe pair.