Cubic Bezier Editor
Free visual cubic-bezier editor for CSS animations. Drag handles to design custom easing curves, preview the animation live, and copy the cubic-bezier() value instantly.
Cubic Bezier Editor - Visual CSS Easing Curve Generator
Design custom CSS easing curves with an interactive visual editor. Drag two control points to shape any cubic-bezier() function, watch the live animation preview, and compare against built-in CSS keywords like ease-in-out. Copy the ready-to-paste CSS code for transition-timing-function and animation-timing-function.
What is a cubic-bezier() easing function?
A cubic-bezier() function describes how a CSS animation or transition progresses over time. Instead of moving at a constant speed, the animation can accelerate, decelerate, overshoot, or bounce based on a curve defined by four numbers.
Syntax: cubic-bezier(x1, y1, x2, y2)
The curve always starts at (0, 0) and ends at (1, 1). The two control points P1 = (x1, y1) and P2 = (x2, y2) pull the curve into shape between them. The x-axis represents time (0 to 1) and the y-axis represents the animation's progress.
If the curve rises sharply at the start, the animation starts fast. If it rises slowly at first and accelerates later, you get an ease-in feel. If y values go below 0 or above 1, the animation will overshoot — this is what creates back/bounce effects.
How do I use this cubic-bezier editor?
Three ways to design your curve:
1. Drag the two blue handles on the canvas to reshape the curve visually. The handles correspond to P1 and P2 in cubic-bezier(x1, y1, x2, y2).
2. Type exact coordinate values into the X1/Y1/X2/Y2 input fields below the canvas if you need precise numbers.
3. Click any preset (ease, ease-in-out, ease-out-back, etc.) to load a well-known curve and modify it from there.
After shaping the curve, press Play to watch a ball animate using your easing. Use the Compare dropdown to run a second ball with a built-in CSS keyword side-by-side, so you can see the difference. The generated CSS code is shown at the bottom — click Copy to paste it into your stylesheet.
For accessibility, the handles are keyboard-focusable: tab to a handle and use arrow keys to nudge it (hold Shift for bigger steps).
What's the difference between ease, ease-in, ease-out, and ease-in-out?
These are the four standard CSS easing keywords, and each maps to a specific cubic-bezier() value:
- ease: cubic-bezier(0.25, 0.1, 0.25, 1) — quick start, slow end. The default if you don't specify a timing function.
- ease-in: cubic-bezier(0.42, 0, 1, 1) — slow start, accelerates toward the end. Useful when an element is leaving the screen.
- ease-out: cubic-bezier(0, 0, 0.58, 1) — fast start, decelerates toward the end. Best for elements entering the screen.
- ease-in-out: cubic-bezier(0.42, 0, 0.58, 1) — slow at both ends, fast in the middle. Symmetric and natural-feeling.
Note that 'linear' is also valid and maps to cubic-bezier(0, 0, 1, 1) — constant speed with no easing. For most UI animations, ease-out is the most polished choice because it gives the impression of physical inertia.
What are overshoot and anticipation curves?
Overshoot curves push the animation past its final value before settling back, creating a playful 'bounce' or 'back' effect. Anticipation curves do the opposite — they pull back slightly before moving forward, mimicking how a real object winds up before launching.
In cubic-bezier() terms, you achieve these effects by setting Y values outside the 0 to 1 range:
- Overshoot (ease-out-back): cubic-bezier(0.34, 1.56, 0.64, 1) — the Y of the second handle goes above 1, so the curve briefly exceeds 100% before settling.
- Anticipation (ease-in-back): cubic-bezier(0.36, 0, 0.66, -0.56) — the Y of the second handle goes below 0, so the value briefly goes negative.
- Strong both-ends: cubic-bezier(0.68, -0.6, 0.32, 1.6).
This editor allows Y values from -2 to 2 so you can experiment freely with overshoot curves. These easings work great for modal dialogs, success checkmarks, and any animation that needs personality.
Where do I use the generated cubic-bezier() value?
You can paste the value into any CSS timing-function property. The two most common are:
1. transition-timing-function on a CSS transition:
.button {
transition: transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
2. animation-timing-function on a @keyframes animation:
.card {
animation: fadeIn 600ms cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
}
The value also works in animation libraries:
- Framer Motion: transition={{ ease: [0.34, 1.56, 0.64, 1] }}
- GSAP: gsap.to(el, { x: 100, ease: 'cubicBezier(0.34, 1.56, 0.64, 1)' })
- Web Animations API: el.animate(frames, { easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)' })
Some tooling such as Material Design 3 motion tokens publish recommended cubic-bezier values — feel free to type those into the X1/Y1/X2/Y2 fields to visualize them.
Are X values restricted to 0–1? Why?
Yes — the X coordinates (x1 and x2) must be between 0 and 1, and this editor enforces that constraint. The reason is mathematical: the X axis represents time, which must move monotonically forward. If a control point's X went outside [0, 1] or back-tracked, the resulting curve could fold over itself, producing two different progress values for the same point in time — which is undefined behavior in CSS.
Y values, however, are free to go outside the 0 to 1 range. Y represents the animation's progress, and progress can legitimately overshoot the destination (a value above 1) or back-track briefly (a value below 0). This is what enables back/bounce effects.
If you enter an X value outside the allowed range, the editor will clamp it back to 0 or 1 automatically.
How does this differ from CSS spring() or linear() easing?
cubic-bezier() is the original CSS easing function, supported in every browser since 2008. It uses two control points to define any single curve.
Newer alternatives:
- linear() function (CSS Easing Functions Level 2): lets you describe an easing as a list of points along the curve. Useful for arbitrary or measured curves that a single bezier can't represent — for example, multi-bounce springs. Supported in modern Chromium, Safari 17.4+, and Firefox 112+.
- @starting-style and view transitions still rely on standard easing functions including cubic-bezier().
- Spring physics (used in Framer Motion, React Spring) is a different model entirely — it simulates a mass-spring system instead of evaluating a fixed curve.
For production CSS today, cubic-bezier() remains the most compatible and predictable choice. Use linear() when you need a true bounce (multiple peaks) that a single bezier can't capture.
Is this tool private? Does it send my curves anywhere?
Yes, completely private. Everything happens in your browser:
- No data is sent to any server
- No accounts, sign-ups, or tracking on your editing
- Works fully offline once the page has loaded
- No external libraries are loaded for the editor itself — it's vanilla JavaScript
- The CSS code you generate stays on your device until you choose to copy it
You can verify this by opening your browser's Network tab while editing the curve — you'll see no requests. The only network activity is the initial page load and shared site assets (fonts, icons).
Key Features
- Interactive drag-and-drop curve editor
- Two draggable control points with live curve update
- Animated preview ball that runs your easing
- Side-by-side comparison with built-in CSS keywords
- Adjustable animation duration from 0.2s to 4s
- 12 named easing presets (ease, ease-in-out, ease-out-back, and more)
- Numeric inputs for precise X/Y control point coordinates
- Supports overshoot and anticipation (Y values from -2 to 2)
- Generates copy-ready cubic-bezier() CSS code
- Outputs both transition-timing-function and animation-timing-function
- Keyboard-accessible handles with arrow-key nudging
- Works with Framer Motion, GSAP, and Web Animations API values
- 100% client-side, no data sent to any server
- Works offline after first load
- Dark mode and mobile-friendly responsive layout
