Keyframe Curve Lab

Design and preview CSS cubic-bezier() easing curves visually.

100% client-side

Curve editor

Preview

cubic-bezier(0.25, 0.1, 0.25, 1)
Preset: ease

What is a cubic-bezier() easing curve?

In CSS, "easing" controls the speed of an animation or transition over time — instead of moving at a constant pace, it can start slow and speed up, or the reverse. cubic-bezier() is the CSS function that defines a custom easing curve using two draggable control points, giving you full control beyond the built-in presets like ease or ease-in-out. This tool lets you drag those control points on a graph, preview the resulting motion live, and copy the exact CSS value.

How to use Keyframe Curve Lab

  1. Drag the two handles on the Curve editor graph, or pick a starting point from the presets (ease, ease-in, ease-out, ease-in-out, linear).
  2. Fine-tune the curve numerically with the X1, Y1, X2, Y2 fields.
  3. Watch the motion in the Preview panel, clicking Replay to run it again.
  4. Click Copy to copy the finished cubic-bezier(...) CSS value.

How cubic-bezier() easing works

A CSS cubic-bezier(x1, y1, x2, y2) timing function is a parametric curve with a fixed start point (0, 0) and end point (1, 1). The two control points you drag, P1 and P2, pull the curve's shape between them. For a parameter t from 0 to 1, the curve's position is:

B(t) = (1-t)³ P0 + 3(1-t)² t P1 + 3(1-t) t² P2 + t³ P3

P0 = (0, 0)      -- animation start, fixed
P3 = (1, 1)      -- animation end, fixed
P1 = (x1, y1)    -- draggable, x1 in [0, 1]
P2 = (x2, y2)    -- draggable, x2 in [0, 1]

The x axis is animation time progress, which browsers constrain to [0, 1] since time only moves forward. The y axis is output progress (how far the animated property has moved toward its end value) and is allowed to leave [0, 1] — a y above 1 or below 0 is exactly what produces overshoot and bounce effects, even though this tool's presets don't use them.

Frequently asked questions

What is a cubic-bezier() easing curve?

It's a CSS timing function defined by two control points, cubic-bezier(x1, y1, x2, y2), that maps animation time progress (x, 0 to 1) to output progress (y). It controls how a CSS transition or animation accelerates and decelerates.

Why is x limited to 0–1 but y isn't?

X represents time, which only moves forward from start (0) to end (1), so browsers clamp it to that range. Y represents output progress and is allowed to go below 0 or above 1, which is what produces bounce and overshoot effects.

How do I use the generated curve in CSS?

Copy the cubic-bezier(...) string and use it as the value of transition-timing-function or animation-timing-function, for example: transition: transform 0.4s cubic-bezier(0.25, 0.1, 0.25, 1);

How do the preset keywords map to cubic-bezier() values?

CSS's named easing keywords are shorthands for fixed control points: ease is cubic-bezier(0.25, 0.1, 0.25, 1), ease-in is cubic-bezier(0.42, 0, 1, 1), ease-out is cubic-bezier(0, 0, 0.58, 1), and ease-in-out is cubic-bezier(0.42, 0, 0.58, 1).