Cubic Bezier & CSS Easing Generator
Shape an easing curve, watch it race the classics and copy CSS, Tailwind or JavaScript.
Easing
Drag the two points, or tap the graph to move the nearest one. A focused point moves with the arrow keys (Shift for bigger steps).
Paste an easing to edit it
Preview
Presets
CSS keywords
Tailwind CSS
Material 3
Penner (fitted cubic-bezier)
Penner (linear() only)
Code
About the Cubic Bezier & CSS Easing Generator
Design the timing of a CSS transition or animation by dragging the two control points of a cubic-bezier() curve. The graph shows time across and progress up, so a curve that rises above the top overshoots its end value and one that dips below the bottom pulls back first. Three lanes play your easing next to two others you pick — CSS’s own ease and ease-in-out, Tailwind’s and Material 3’s curves, or the classic Penner easings such as easeOutBack — and a time slider freezes all of them at the same moment.
Some motion cannot be drawn with one Bézier curve: a spring that wobbles, a ball that bounces, an elastic snap. For those the tool computes the motion exactly (a damped spring from stiffness, damping and mass; a bouncing ball from its bounciness) and writes it as the newer CSS linear() function with as many points as you choose, with the largest error shown. steps() easings are here too. Copy the result as CSS (with a cubic-bezier() fallback for older browsers), as a Tailwind class or theme variable, or as Web Animations API code.
How to use it
- Choose the kind of easing: Cubic Bézier, Spring, Bounce, Elastic or Steps — or start from a preset at the bottom.
- For a Bézier curve, drag the two numbered points (or tap the graph to move the nearer one), or type x1, y1, x2 and y2. Mirror turns an ease-in curve into the matching ease-out.
- For a spring, bounce or elastic easing, move the sliders, then set how many points the
linear()gets; the summary shows how close it stays to the exact motion. - Watch the Preview lanes, pick other easings to compare, change the duration, or drag Time to compare the positions at one moment.
- Under Code, name the easing and copy the CSS, Tailwind or JavaScript — or select Copy value for just the timing function.
Examples
Preset: easeOutBack
cubic-bezier(0.333, 1.567, 0.667, 1)
Penner’s ease-out back is a cubic polynomial, so a cubic Bézier with x1 = 1/3 and x2 = 2/3 reproduces it exactly (up to rounding).
Spring: stiffness 180, damping 12, mass 1
--ease-spring: linear(0, 0.002 0.44%, 0.009 0.88%, 0.02 1.35%, …, 1); transition: transform 1137ms var(--ease-spring);
The damping ratio is 12 ÷ (2·√180) ≈ 0.45, so it overshoots by about 21% before settling. 1137 ms is the time it needs to stay within 0.1% of the end; 40 points keep the linear() within 0.24% of the exact motion.
Steps: 60, jump-end
animation: tick 60s steps(60) infinite;
Common uses
- Giving buttons, menus and dialogs motion that feels quick but not abrupt, with one named easing used across a design system.
- Replacing a JavaScript spring or bounce animation with plain CSS that runs on the compositor.
- Matching an easing from a design tool or another library, or checking what a cubic-bezier() you found does.
- Teaching how timing functions work by comparing them side by side.
How cubic-bezier() works
A timing function maps the share of time that has passed (x, 0 to 1) to the share of the change that is done (y). cubic-bezier(x1, y1, x2, y2) is a Bézier curve from (0, 0) to (1, 1) whose shape is set by two control points. The x values must stay between 0 and 1, because time cannot run backwards; the y values may go beyond, which is how overshoot and anticipation are made (CSS Easing Functions). The keywords are curves too: ease is cubic-bezier(0.25, 0.1, 0.25, 1), ease-in (0.42, 0, 1, 1), ease-out (0, 0, 0.58, 1) and ease-in-out (0.42, 0, 0.58, 1).
Springs, bounces and linear()
linear() draws straight lines between points you list, such as linear(0, 0.6 40%, 1) — at 40% of the time it is 60% done. With enough points it can follow any motion, including several overshoots, which one Bézier curve cannot. The spring here solves the equation of a damped spring (m·x″ + c·x′ + k·x = 0) exactly; with a damping ratio c ÷ (2√(k·m)) below 1 it overshoots, at 1 it is the fastest motion without overshoot. Where the curve bends places points where the motion changes direction (and on every impact of a bounce), which keeps the error low with few points; Evenly spaces them in time so the CSS needs no percentages. linear() works in Chrome and Edge 113, Firefox 112 and Safari 17.2 and later (MDN); the code adds the closest cubic-bezier() for older browsers.
The named easings
Robert Penner’s easing equations (sine, quad, cubic, quart, quint, expo, circ, back, elastic and bounce, each as in, out and in-out) are formulas, so a cubic-bezier() can only approximate most of them. The presets here are least-squares fits whose largest error is checked against each equation; quad, cubic and back in and out are polynomials of degree three or less, which a cubic Bézier matches exactly. Easing lists elsewhere sometimes give rounder numbers: cubic-bezier(0.34, 1.56, 0.64, 1) for easeOutBack, for example, is up to 0.5% off the equation. Elastic and bounce cannot be one curve at all, so they load as linear(). The Tailwind values are its --ease-in, --ease-out and --ease-in-out theme variables and the Material 3 values are the md-sys-motion easing tokens (material-web).
steps()
steps(n, position) jumps between n held values instead of moving smoothly. The position decides where the jumps happen: jump-end (the default, also written end) holds the start value first and reaches the end value only when the time is up; jump-start (start) jumps immediately; jump-none holds both the start and the end value and needs at least 2 steps; jump-both jumps at both ends. step-start and step-end are steps(1, start) and steps(1, end).
Limitations
- The fallback cubic-bezier() for a spring, bounce or elastic easing can only follow one overshoot; browsers without linear() get a simpler motion.
- A linear() easing with many points makes a long CSS value. Fewer points with Where the curve bends are usually enough: the summary shows the error.
- The preview moves dots; how an easing feels also depends on the duration, the distance and the property you animate.
- If your device is set to reduce motion, the preview plays only when you select Play. Use
@media (prefers-reduced-motion: reduce)to tone down large movements on your own site.
Privacy
Everything happens in your browser. What you enter or open here is not uploaded or stored by MySmartCoPilot.
Frequently asked questions
What do the four numbers in cubic-bezier() mean?
They are the x and y of the two control points: cubic-bezier(x1, y1, x2, y2). The curve starts at (0, 0), heads towards (x1, y1), comes in from (x2, y2) and ends at (1, 1). x is time and must be between 0 and 1; y is progress and may be outside 0–1 for overshoot.
How do I make a CSS spring or bounce animation?
Choose Spring or Bounce, adjust it until the preview feels right, and copy the CSS: it is a linear() timing function with the duration the spring needs to settle. Use it like any easing, e.g. transition: transform 1137ms var(--ease-spring).
Why is my cubic-bezier for easeOutBack different from other sites?
The named easings are equations, and a cubic-bezier() is either an exact match (quad, cubic and back in and out) or an approximation. The numbers here are fitted to the equations and checked; some lists round them, so their curves differ slightly. Both are valid CSS.
How do I use a custom easing in Tailwind CSS?
For one element, use the arbitrary value such as ease-[cubic-bezier(0.34,1.56,0.64,1)] (commas, no spaces). To reuse it, add --ease-pop: cubic-bezier(0.34, 1.56, 0.64, 1); to @theme (Tailwind CSS v4) and write ease-pop. The Tailwind tab writes both.
Can I use the easing with JavaScript animations?
Yes. The Web Animations API takes the same strings: element.animate(keyframes, { duration: 600, easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)' }). The JavaScript tab writes it with a check for linear() support.
Is anything uploaded?
No. Everything is calculated in your browser, and the page works offline once loaded. A copied link keeps the settings after the # in the address, which browsers do not send to servers.