---
title: "CSS Cubic-Bezier Easing Generator"
description: "Free cubic-bezier() editor: drag the curve, start from ease or easeOutBack, preview it against linear and copy the CSS plus a linear() version."
url: https://frontendhelpers.com/cubic-bezier-generator
updated: 2026-10-12
---

# Cubic-bezier easing generator

Drag the two control points to shape a CSS easing curve, start from the built-in keywords or well-known named curves, watch it race a linear box, and copy it as `cubic-bezier()` or as a `linear()` approximation.

## How cubic-bezier() works

Every CSS transition and animation has a timing function that maps elapsed time to progress. `cubic-bezier(x1, y1, x2, y2)` describes that mapping as a curve that always starts at (0, 0) and ends at (1, 1). The four numbers are the two control points in between: P1 shapes the start of the motion and P2 shapes the end. Pull P1 along the time axis and the animation starts slowly; lift it steeply and it leaps off the mark. That is why `ease-out`, `cubic-bezier(0, 0, 0.58, 1)`, rises sharply at first and flattens out, and `ease-in`, `cubic-bezier(0.42, 0, 1, 1)`, does the reverse.

The keywords are just names for fixed curves: `ease` is `cubic-bezier(0.25, 0.1, 0.25, 1)`, `ease-in-out` is `cubic-bezier(0.42, 0, 0.58, 1)`, and `linear` behaves like `cubic-bezier(0, 0, 1, 1)`. `ease` is also the default when you write a transition without a timing function, which is why so many interfaces share the same slightly front-loaded feel. Pick a keyword in the editor and the table shows how different they really are: at the halfway point in time, `ease` has already covered about 80% of the distance.

## Why x stays in 0–1 but y can overshoot

The x axis is time, and time only moves forward. If a control point's x went below 0 or above 1, the curve could loop back so that one moment had two different progress values, which makes no sense for an animation. The specification therefore requires both x values to be between 0 and 1, and browsers throw the whole declaration away if they aren't. This editor clamps x so the CSS it gives you is always valid.

The y axis has no such limit. A y value above 1 makes the motion travel past its end point and settle back, as in `easeOutBack`, `cubic-bezier(0.34, 1.56, 0.64, 1)`. A y below 0 makes it pull back before setting off, the anticipation you see in `easeInBack`. Use these sparingly: a small overshoot on a button press or toast feels lively, but on a menu or a page transition it tends to look like a glitch. Note that overshoot can push an element outside its container, and for `opacity` the extra range is simply clipped.

## Choosing an easing for interface motion

Nielsen Norman Group's guidance on [animation duration and motion](https://www.nngroup.com/articles/animation-duration/) sums up the common pattern. Things entering the screen should ease out, arriving quickly and slowing as they come to rest, because the user is waiting for them. Things leaving should ease in, starting gently and accelerating away, because the user has already finished with them. For timing, NN/g suggests most UI animations fall between about 100 and 500 ms, with 100–400 ms right for most, and exits slightly shorter than entrances. A third common rule: an element that moves from one place on screen to another reads best with an ease-in-out curve, which accelerates and then brakes like a physical object.

In practice that means short durations with a strongly decelerating curve for most entrances. `easeOutExpo` or `easeOutQuart` at 200–300 ms makes a panel or dropdown feel responsive without a visible slow start. Reserve longer durations for large surfaces that travel a long way. Whatever you choose, apply it consistently through a custom property, for example `--ease-out: cubic-bezier(0.16, 1, 0.3, 1);`, so the whole interface moves with one character. Browse our [library of CSS animations](https://frontendhelpers.com/css-animations) for effects to try your curve on, and see the [native dialog animation recipe](https://frontendhelpers.com/css-dialog-animation) for a real entrance and exit pair.

Easing also affects how smooth a transition looks. A curve that changes speed sharply concentrates movement into fewer frames, so any jank is more visible. Animate `transform` and `opacity` where you can; our guide to [CSS animation performance](https://frontendhelpers.com/css-animation-performance) explains why. And honour `prefers-reduced-motion`: replace large movement with a fade, or remove it, for visitors who ask for less motion. The preview on this page follows the same rule and won't start by itself when that setting is on.

## Springs and bounces with linear()

A cubic Bézier has only two control points, so it can bend in limited ways: it can overshoot at the end or dip at the start, but it cannot oscillate. Springs that wobble before settling and bounces that hit the floor several times need more. The `linear()` function covers that. It takes a list of progress values, each with an optional position in time, and joins them with straight lines: `linear(0, 1.2 60%, 0.9 80%, 1)` overshoots, dips back below the target and settles. With enough points, any curve can be approximated closely, which is how spring generators export their output.

According to MDN's compatibility data, `linear()` works in Chrome and Edge 113, Firefox 112 and Safari 17.2 onwards. The generator above samples your curve and keeps only the points needed to stay within about 0.001 of it, usually 18 to 35 stops. That is useful as a starting point for hand-tuning, or for adding a bounce after your curve. For a plain curve, `cubic-bezier()` is exact and shorter, and has worked in every browser for over a decade. To support older Safari with `linear()`, declare a `cubic-bezier()` fallback first and the `linear()` version after it; browsers that don't understand the second declaration keep the first.

## steps() for frame-by-frame motion

The third kind of timing function doesn't interpolate at all. `steps(4, jump-end)` divides the duration into four equal parts and jumps between values, which suits sprite-sheet animation, a ticking clock hand or a typewriter effect. The second argument sets where the jumps happen: `jump-start` jumps at the beginning of each interval, `jump-end` (the default) at the end, `jump-none` holds both the first and last values, and `jump-both` adds a jump at each end. The shorthands `step-start` and `step-end` mean `steps(1, jump-start)` and `steps(1, jump-end)`.

## Frequently asked questions

### What do the four numbers in cubic-bezier() mean?

They are the coordinates of two control points, P1 (x1, y1) and P2 (x2, y2). The curve always runs from (0, 0) to (1, 1): x is the fraction of the duration that has passed and y is how far the animation has progressed. The control points pull the curve and set where it speeds up and slows down.

### Why must x stay between 0 and 1 in cubic-bezier()?

x is time. If a control point's x went outside 0 to 1, the curve could double back so that one moment mapped to two different progress values. Browsers reject such a value as invalid, so this editor clamps x. y has no limit, which is how overshoot and anticipation effects are made.

### When should I use linear() instead of cubic-bezier()?

Use linear() when the motion must change direction more than a cubic Bézier allows, such as a spring that wobbles before settling or a ball that bounces. linear() takes any number of points joined by straight lines. It works in Chrome and Edge 113, Firefox 112 and Safari 17.2 onwards.

### Which easing should I use for UI animations?

Use ease-out for elements entering the screen, ease-in for elements leaving it, and ease-in-out for something moving from one place on screen to another. Keep most interface transitions between about 100 and 400 ms, with exits a little quicker than entrances.

## Related tools

- [CSS Animations](https://frontendhelpers.com/css-animations): Copy-ready keyframe animations to try your easing curve on.
 
- [CSS animation performance](https://frontendhelpers.com/css-animation-performance): Which properties animate smoothly, and how to avoid jank.
 
- [Animate a native dialog](https://frontendhelpers.com/css-dialog-animation): An entrance and exit pair using @starting-style and allow-discrete.

---

This page is a free interactive tool. Use it in your browser at https://frontendhelpers.com/cubic-bezier-generator
