A CSS cubic-bezier easing curve is defined by exactly four numbers, x1, y1, x2, and y2, that describe two intermediate control points on a parametric curve running between the fixed start point (0, 0) and the fixed end point (1, 1). The curve plots input-time progress on the horizontal axis against output progress of the animated value on the vertical axis, so each input fraction of elapsed time maps to a specific output fraction of how far the animation has actually traveled. Beginners should know this shape and its two hard rules before they generate a CSS cubic bezier: the x1 and x2 coordinates describe input time and CSS requires both to stay inside the closed 0 to 1 range, while the y1 and y2 coordinates describe output progress and may legitimately leave that range to create anticipation below 0 or overshoot above 1. Knowing what each number means, what each one is allowed to do, and what the resulting timing function actually controls lets you make deliberate choices instead of guessing until something looks right on screen.
The rest of this guide walks through the four numbers, the keyword presets, the generator's working steps, what it intentionally does not produce, and how to confirm your easing behaves the way you expect in a real component.

The Four Numbers Behind Every CSS Cubic Bezier
A valid cubic-bezier() value contains four numbers and only four numbers. The first pair, x1 and y1, describes the position of the first control point. The second pair, x2 and y2, describes the second. The start point of the curve is always (0, 0), representing zero progress at zero time, and the end point is always (1, 1), representing full progress at full time. You never write those two anchor points; the CSS specification adds them for you.
What this means in practice is that the four editable numbers shape a parametric curve whose overall character depends on all four together rather than on any single value in isolation. Move x1 closer to 1 and the animation commits to making most of its visible motion early in the duration. Pull y2 below 0 and the value drifts backwards before snapping forward. Push y2 above 1 and the value lands past its target and the easing settles back. The two coordinates of each control point are linked by the underlying curve geometry, but the rules the browser applies to x and y are very different, which is the next thing a beginner needs to understand.
Why x Must Stay in 0–1 but y Can Roam
W3C CSS Easing Functions Level 1, the specification that defines cubic-bezier, declares a curve invalid if either x control coordinate sits outside the closed 0 to 1 range. The reason is functional rather than aesthetic: x represents input time. If x1 were, say, 1.2, then a fraction of elapsed time greater than 100 percent would be required to reach that control point's influence, which has no physical meaning inside an animation whose total duration is fixed. The generator enforces this rule directly by constraining its x inputs to the valid range and rejecting any value the underlying calculator cannot process into a valid timing function.
The y coordinates are a different story. They represent output progress, and a value can legitimately exceed 100 percent of the target or dip below zero. A y2 of 1.2 produces overshoot, meaning the animated value lands slightly past its target and the easing settles back. A y2 of -0.2 produces anticipation, meaning the value briefly moves backwards before its forward motion begins. Both behaviors are part of how cubic-bezier can imitate the spring-like motion designers often want, and both are explicitly allowed by the spec. The generator accepts finite y values from minus ten to ten to give you room to experiment with strong overshoot and anticipation while still rejecting runaway inputs that would distort the result.
You will notice that extreme y values can make the parametric curve leave the visible square of the chart. That is a display choice rather than a clamp of the data: the chart keeps a stable zero-to-one frame so ordinary timing curves remain easy to compare side by side. The sample table and the moving preview always use the actual computed easing, so overshoot is real even when the chart appears to clip it.
The Five Keyword Presets and What They Mean
CSS ships five built-in easing keywords. Each one maps to a specific pair of control coordinates, defined in W3C CSS Easing Functions Level 1 and documented on MDN. The generator exposes these as one-click presets and loads their standardized control points into the four editable fields so you can read, compare, and modify them rather than accepting a hidden default. The exact mappings are listed in the table below.
| Keyword | x1 | y1 | x2 | y2 | Behavior |
|---|---|---|---|---|---|
| linear | 0 | 0 | 1 | 1 | Constant speed from start to end. |
| ease | 0.25 | 0.1 | 0.25 | 1 | Gentle acceleration, fast middle, soft landing. The default for CSS transitions. |
| ease-in | 0.42 | 0 | 1 | 1 | Slow start, full speed by the end. Reads as motion leaving the screen. |
| ease-out | 0 | 0 | 0.58 | 1 | Full speed at the start, gentle landing. Reads as motion arriving on screen. |
| ease-in-out | 0.42 | 0 | 0.58 | 1 | Slow start and slow end with a fast middle. Reads as motion passing through. |
Note that choosing a keyword in the generator does not output the keyword itself. The visible declaration always exposes all four numbers, for example cubic-bezier(0.42, 0, 0.58, 1), so the curve can be recorded, compared, and modified without hidden defaults. Linear is shorthand for cubic-bezier(0, 0, 1, 1); the generator writes the four-number form so the curve stays auditable.
How to Generate a CSS Cubic Bezier
The generator follows a three-step workflow that takes you from a blank curve to a verified timing function ready for production CSS.
- Choose a starting point. Pick one of the five CSS easing keywords to load its standardized control coordinates into x1, y1, x2, and y2, or enter the four numbers directly if you already have a target curve in mind.
- Review the graph, samples, and motion. Watch the parametric plot, read the five input-to-output samples at t = 0, 0.25, 0.5, 0.75, and 1, and toggle the Run preview to watch a circle move between two positions using a 900 millisecond transform transition driven by the exact generated easing.
- Copy the declaration and test it. Use the Copy CSS control to write the complete transition-timing-function declaration, including its semicolon, to the clipboard. If browser policy denies clipboard access, the declaration remains visible and selectable and the status does not claim success, so the value can still be copied manually. Then paste it into the real property, distance, duration, and surrounding component to confirm the timing reads the way you intended.
You can iterate between steps freely. Editing any of the four numbers updates the graph, the samples, the preview, and the copied declaration immediately. Numbers are rounded to three decimal places only when the declaration is serialized for the clipboard; the underlying calculation keeps full JavaScript numeric precision so the curve itself does not drift between edits.
What the Generator Does Not Produce
The tool focuses on one cubic-bezier timing function so its output stays predictable and easy to audit. It does not generate keyframes, spring physics, linear() stop lists, steps(), duration values, delay values, iteration counts, or a full transition shorthand. You still choose the animated property (transform, opacity, background-color, and so on), the distance, the duration, the delay, and any reduced-motion behavior.
The distinction matters because cubic-bezier describes timing only. Two animations with the same easing and the same duration but different properties will not feel identical. A 300 millisecond opacity cross-fade and a 300 millisecond transform slide of the same distance occupy the same shape on the curve but read differently to a viewer because of how the eye interprets each property. Treat the easing as one ingredient rather than the whole recipe, and choose the other values deliberately around it.
For a related workflow that focuses on the choice of approach rather than the math itself, see Pick the Right Approach to Generate a CSS Cubic Bezier. For a deeper walkthrough of the verification stage that step three of the workflow above depends on, see Check the Result After You Generate a CSS Cubic Bezier.
Reading the Sample Table and the Moving Preview
The sample table answers a question the control-point diagram alone cannot: at a given fraction of elapsed time, how far has the animated value actually progressed? For each input at 0, 0.25, 0.5, 0.75, and 1, the solver finds the curve parameter whose x coordinate equals the requested input and then evaluates y at that parameter. It first uses bounded Newton iterations and finishes with bisection when Newton would step outside the safe range. This combination avoids the common mistake of treating the curve parameter t as elapsed time, which only holds true when both x control coordinates sit at exactly 0 and 1.
The Run preview shows the same easing applied to a real CSS transition: a circle toggling between two horizontal positions using a 900 millisecond transform transition. Repeated clicks let you compare forward and reverse motion, and the actual computed easing drives the timing regardless of how the chart happens to look. If overshoot matters for your design, inspect the moving element and the numeric samples rather than assuming a chart that appears clipped means the value was clamped.
Test the Easing in Real Code and Respect Motion Preferences
The preview demonstrates timing, not production performance under every workload. A real component can feel different when distance, duration, property, rendering cost, input device, or surrounding motion changes. Paste the declaration into its final interface, the actual property, the actual distance, the actual duration, and judge the motion there.
CSS permits curves that are technically valid but unpleasant or confusing in real interfaces. Large overshoots can make controls appear to reverse direction, leave their container, or reveal content that was expected to remain clipped. A valid curve is not automatically accessible, performant, or appropriate. Keep important state changes understandable without motion, avoid rapid oscillation, and check focus and pointer behavior while an element is transitioning. For users who prefer reduced motion, the easing becomes irrelevant if you have already disabled the animation at the prefers-reduced-motion media query, so plan the disabled path before you ship the animated one.
When you are ready to build the curve itself, the CSS Cubic Bezier Generator handles the math, the validation, and the rounding in the browser, and nothing about your curve, your CSS, or your interactions is uploaded, stored, or sent to an animation service. The full specification at CSS Easing Functions Level 1 and the MDN reference at cubic-bezier() document the syntax, the validity rule, and the keyword mappings the generator implements.