A CSS cubic-bezier timing function is defined by exactly four numbers, x1, y1, x2, and y2, placed between a fixed start point at (0, 0) and a fixed end point at (1, 1), and choosing the right approach to generate one means deciding whether to start from one of the five standardized CSS easing keywords or to hand-tune those four coordinates to match the motion you actually want. The keyword route is fast, predictable, and matches what browsers have shipped since the earliest animation support, while the custom route is the only way to introduce anticipation, overshoot, or a brand-specific feel. Most projects mix both: keywords for ordinary interface motion and custom curves for the handful of moments where timing is part of the design. The CSS Cubic Bezier Generator is built around that exact decision. It loads the five keywords as live presets, exposes all four coordinates as editable numbers, and shows the resulting curve as a graph, a sampled progress table, and a moving preview so you can compare approaches before committing to one.

How a CSS Cubic Bezier Is Actually Defined
The cubic-bezier() function in CSS takes four numeric arguments, which CSS Easing Functions Level 1 calls the x1, y1, x2, and y2 control coordinates. The curve is anchored at (0, 0) on the left edge of the easing graph and at (1, 1) on the right edge, and the two intermediate control points shape the slope of the curve as it travels from start to end. Because the x axis represents elapsed input time, CSS requires both x1 and x2 to lie inside the closed range from zero to one; a value outside that range makes the declaration invalid and the browser falls back to its default easing. The y axis represents output progress, so y1 and y2 are allowed to fall below zero or rise above one, and that is what creates anticipation before motion and overshoot at the end of motion.
The five CSS easing keywords, linear, ease, ease-in, ease-out, and ease-in-out, are standardized shortcuts for specific sets of those four coordinates. According to W3C CSS Easing Functions Level 1, those keywords map to fixed values that have been part of CSS animations and transitions for many years. Because the keywords are standardized, any browser that supports cubic-bezier() supports the keywords, and any team member can read the timing without consulting a generator.
The Two Main Approaches: Preset Keyword or Custom Control Points
Every cubic-bezier curve you can ever write comes from one of two workflows. The first is to pick a preset keyword or its standardized numeric form, paste it into a transition or animation, and move on. The second is to design a custom curve, either by adjusting the four control points visually until the motion looks right, or by reverse-engineering a timing feel you already like.
Most of the time the keyword approach is the right call. The standardized curves cover the most common motion needs: constant speed (linear), a gentle start and settle (ease), slow start with a confident finish (ease-out), hesitant start with a strong push (ease-in), and symmetric acceleration and deceleration (ease-in-out). They are easy to read, easy to copy, and they survive team handoffs without explanation. The custom approach earns its place when the standard set does not match the motion the design calls for: a button that nudges forward before activating, a modal that overshoots its resting position and settles back, or a chart transition that should feel slower at the start and faster near the end without snapping to ease-in.
The decision rarely needs to be made in the abstract. The shape of the project, the audience, and the property being animated usually make the answer obvious once you look at the timing you actually want.
When a Preset Easing Keyword Is the Right Choice
Reach for a preset when the motion is conventional, the audience expects the curve to behave the way every other interface behaves, and the cost of tuning by hand exceeds the value of the tuning. That covers most hover effects, most fades, most state changes on small UI elements, and almost every tooltip or dropdown where consistency with the rest of the system matters more than distinctiveness. The five standardized curves also work well for accessibility: they are well known to motion designers, they sit comfortably on the chart, and they rarely produce extreme behavior that could disorient a user.
The table below lists the keyword values defined by CSS Easing Functions Level 1. These are the exact numeric control points the generator loads when you press one of the keyword buttons.
| Keyword | x1 | y1 | x2 | y2 | Common use |
|---|---|---|---|---|---|
| linear | 0 | 0 | 1 | 1 | Constant speed, looping motion, color fades |
| ease | 0.25 | 0.1 | 0.25 | 1 | Default for many browsers, gentle start and settle |
| ease-in | 0.42 | 0 | 1 | 1 | Elements leaving the screen, decisive arrivals |
| ease-out | 0 | 0 | 0.58 | 1 | Elements arriving on screen, confident stops |
| ease-in-out | 0.42 | 0 | 0.58 | 1 | Symmetric motion, page-level transitions |
These values are the standardized reference points the generator keeps as tested cases, so pressing a keyword button in the tool loads exactly the same coordinates rather than approximating them from memory.
When Custom Control Points Earn the Extra Effort
Custom control points are worth the effort when the motion has to do something the keyword set cannot express. The clearest example is overshoot, where the animated value passes its target before settling back; the only way to get that in CSS without keyframes is to set y2 above one. Anticipation is the mirror case, a small backward pull before forward motion, and that requires a y value below zero. Brand-specific timing, where a product wants every transition to feel like a particular physical material, also benefits from custom curves, because the keywords are intentionally generic.
Custom curves also help when the property being animated is unusual. A long transform over a long distance can feel flat under ease-in-out but come alive with a custom curve that has a sharper middle and a softer landing. A short opacity fade can feel sluggish under ease-in and snappy under a custom curve whose y1 stays near zero for the first 30 percent of input progress. The reason to step away from keywords is not novelty but fit.
Two constraints govern what you can type. The x coordinates must stay between 0 and 1 because they describe input-time positions; values outside that range make the cubic-bezier() declaration invalid. The y coordinates describe output progress and may be any finite value from -10 to 10 inside the tool, which is wide enough to express strong anticipation or overshoot without producing curves that are technically valid but impossible to use. If you want a refresher on how those y values behave, the explanation of y1 and y2 leaving the 0–1 range walks through the practical effects.
How to Pick the Right Approach in the CSS Cubic Bezier Generator
The CSS Cubic Bezier Generator is built to make the preset-versus-custom decision explicit. Both routes produce the same artifact, a complete transition-timing-function declaration, and the steps below cover how to choose one and confirm it before you copy.
- Open the CSS Cubic Bezier Generator and decide whether the motion you want is conventional or unusual. If it is conventional, click one of the five keyword buttons, linear, ease, ease-in, ease-out, or ease-in-out, to load the standardized control coordinates; if it is unusual, clear the inputs and type your own x1, y1, x2, y2 values within the allowed ranges.
- Inspect the graph to confirm the curve's shape matches the intent. Standard curves should sit inside the visible square; if you deliberately choose extreme y values, parts of the curve can extend outside that frame on purpose and the actual computed easing still controls the sample table and the preview.
- Read the five numeric samples, which show output progress at 0, 0.25, 0.5, 0.75, and 1 of input progress. The tool solves for the curve parameter whose x coordinate matches the requested input before evaluating y, so the value at 0.5 input progress reflects elapsed time rather than the curve parameter at 0.5.
- Click Run preview to watch a 900 millisecond transform transition play between two positions using the exact generated easing string. Repeat the click to compare forward and reverse motion and to feel the curve on a representative distance.
- Copy the declaration when the curve reads well. The tool serializes all four coordinates, even when the curve came from a keyword, so the result can be recorded, diffed, and modified without hidden defaults. The copied text includes the trailing semicolon so it can be pasted directly into a stylesheet.
- Replace the generated easing in the real component, on the real property, with the real distance and duration, and confirm the motion under those conditions. The preview demonstrates timing, not production performance, so the final test belongs in the final interface.
Validating the Curve Before You Commit
Three quick checks catch most of the problems that show up after a curve ships. First, confirm the x values are inside 0 to 1; the generator will not let you type values outside that range for x1 or x2, so a problem here usually means the value was edited after the curve was pasted. Second, scan the sample table for any value that surprises you. If the sample at 0.25 input progress is far from 0.25 output progress, the curve is more aggressive than ease-in or ease-out, which may or may not be the intent. Third, run the preview forward and reverse several times to feel the curve at the beginning, middle, and end.
If the curve passes those checks, copy the declaration and test it in context. If something feels off, adjust the y values rather than the x values whenever possible, because moving y changes the shape of the curve without affecting the timing of the input progress, and that keeps the total duration predictable. The comparison guide on how to use cubic-bezier CSS for custom easing covers additional patterns for tuning y values without breaking the input timeline.
Applying the Chosen Curve in Real CSS
The generator outputs only the transition-timing-function value, and the rest of the transition still belongs to you. The four pieces that matter are the animated property, the distance, the duration, and the timing function itself. A curve that feels right on a 16 pixel hover state can feel completely different on a 320 pixel modal, so the same numbers should not be expected to work everywhere. Match the duration to the distance, match the easing to the property, and respect reduced-motion preferences where the animation is not essential to the meaning of the change.
Because the generator exposes all four numbers in the copied declaration, the curve can be reviewed by a teammate, recorded in a design system, and version-controlled with the rest of the stylesheet. The keyword buttons in the tool load standardized values, but the output is always the explicit four-number form, so the file you commit never contains a magic keyword that drifts between libraries. That is the practical difference between a generated curve you can audit and a curve that is technically valid but impossible to read.