Cubic-Bezier Editor

Design custom easing curves visually with an interactive bezier editor. Preview animations in real time and export CSS or Tailwind classes.

P1P2
P10.40, 0.00
P20.20, 1.00
cubic-bezier(0.40, 0.00, 0.20, 1.00)
CSS
transition-timing-function: cubic-bezier(0.40, 0.00, 0.20, 1.00);
Tailwind CSS
<div class="transition-all duration-500 ease-[cubic-bezier(0.40,_0.00,_0.20,_1.00)]">
  ...
</div>

A cubic-bezier easing curve controls how an animation's progress accelerates and decelerates over its duration. In CSS, the animation-timing-function and transition-timing-function properties accept cubic-bezier(x1, y1, x2, y2), where the four numbers define the two control handles of a curve that runs from (0,0) to (1,1). The x axis is elapsed time and the y axis is animation progress, so the shape of the curve is literally the motion your users feel.

This editor makes those four abstract numbers tangible. You drag the two control points on an interactive grid, watch a live element animate against the curve in real time, and copy the resulting cubic-bezier() value straight into your stylesheet or grab a ready-made Tailwind arbitrary-value class. It replaces the trial-and-error loop of editing numbers, reloading, and squinting at the result.

The named keywords you already know are just presets of this same function: ease is cubic-bezier(0.25, 0.1, 0.25, 1), ease-in is cubic-bezier(0.42, 0, 1, 1), and linear is cubic-bezier(0, 0, 1, 1). Once you understand that, you can go beyond the built-ins and design timing that matches your product's specific feel, including overshoot curves that briefly exceed the 0-to-1 range for a springy, bouncy finish.

Building a curve step by step

  1. 1

    Drag the two control-point handles on the grid to shape the curve. The first handle sets x1/y1 (how the motion starts) and the second sets x2/y2 (how it ends); pulling a handle upward front-loads or tails progress, while spreading them along the time axis changes pacing.

  2. 2

    Watch the live preview animate as you edit. Replay it to feel the difference between a slow start, a hard stop, and an overshoot, rather than judging the curve by its shape alone.

  3. 3

    Fine-tune the numeric coordinates when you need precision. x1 and x2 must stay between 0 and 1, but y1 and y2 can go below 0 or above 1 to create anticipation and overshoot effects.

  4. 4

    Compare against a preset (ease, ease-in-out, linear) as a starting baseline, then nudge from there instead of designing from a flat line.

  5. 5

    Copy the output as a cubic-bezier() value for plain CSS, or as a Tailwind class such as ease-[cubic-bezier(0.34,1.56,0.64,1)], and paste it into your transition or animation declaration.

When you would reach for this

  • Signature UI motion

    Designing a consistent easing language for a design system so buttons, modals, and menus share one recognizable feel instead of a mix of default ease and ad-hoc guesses.

  • Overshoot and spring effects

    Creating a subtle bounce on a toast, dropdown, or card by pushing y values past 1, giving the illusion of physical momentum without pulling in a JavaScript animation library.

  • Matching a motion spec

    Reproducing an easing curve a designer specified in Figma, After Effects, or a spec doc by dragging until the preview matches, then exporting the exact coordinates for hand-off.

  • Fixing sluggish transitions

    Replacing the browser default ease on hover and enter states with a curve that starts faster and settles gently, so interactions feel responsive rather than heavy.

Practical notes and gotchas

  • Only x1 and x2 are clamped to the 0-1 range; the browser will reject a curve whose x values fall outside it, but y can legally exceed those bounds, which is exactly how overshoot curves work.
  • Respect prefers-reduced-motion. Wrap non-essential animations in a @media (prefers-reduced-motion: reduce) query and drop the easing to a near-instant transition, since aggressive overshoot can trigger vestibular discomfort.
  • For genuinely physics-based motion, consider CSS linear() (an approximated spring via many stops) or the newer spring options in JS libraries; cubic-bezier only has two control points, so a true multi-bounce spring is not possible with it.
  • Keep durations honest. A dramatic curve on a 600ms+ transition feels slow; most UI motion lands between 150ms and 400ms, and the curve shapes that window rather than replacing a sensible duration.
  • cubic-bezier() animates on the main thread only for cheap properties. Stick to transform and opacity to stay on the compositor and avoid jank; easing a width or top change will still cause layout thrashing no matter how good the curve is.

Common questions about easing curves

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

They are the coordinates of two control points, written as cubic-bezier(x1, y1, x2, y2). The curve always runs from (0,0) to (1,1) where x is time and y is animation progress, and the two points bend that curve to define acceleration.

Can y values be greater than 1 or less than 0?+

Yes. The y coordinates (y1 and y2) are unbounded, which lets the curve overshoot past the end value or dip below the start for anticipation and bounce effects. The x coordinates, however, must stay within 0 and 1.

What is the difference between ease, ease-in, ease-out, and ease-in-out?+

They are named presets of cubic-bezier(). ease-in accelerates from a slow start, ease-out decelerates into a slow finish, ease-in-out does both, and the default ease is a mild ease-in-out equal to cubic-bezier(0.25, 0.1, 0.25, 1).

Do custom cubic-bezier curves work in all browsers?+

Yes. cubic-bezier() is supported in every modern browser and has been for many years, so custom curves are safe to ship without a fallback. The newer linear() timing function for spring approximations has narrower support.

How do I use a custom curve in Tailwind CSS?+

Use an arbitrary value on the ease utility, for example ease-[cubic-bezier(0.34,1.56,0.64,1)], and remove any spaces inside the value. You can also register named easings under theme.transitionTimingFunction for reuse.

Why does my animation still look off even with a good curve?+

The curve only shapes timing; duration, the property being animated, and frame performance matter just as much. Animating layout properties like width or margin causes reflow, so switch to transform and opacity and check that your duration suits the interaction.