Quick Answer

The CSS cubic-bezier() function defines a custom easing curve for transitions and animations using two control points. Use cubic-bezier(x1, y1, x2, y2) as a transition-timing-function value to escape the five built-in keywords (ease, linear, etc.) and design motion that matches your brand. This editor lets you drag the control points and copy the resulting CSS.

Cubic Bezier Editor

Updated

Cubic-bezier curves are the foundation of smooth CSS animations. Instead of relying on generic easing keywords like ease-in-out, you can design custom timing functions that match your brand's motion language. This visual editor lets you drag control points directly on a graph, see the resulting animation in real-time, and copy a ready-to-use CSS snippet. All four presets from the CSS specification are included, and you can share your custom curve with anyone via the URL.

Most "smooth" animations on the web are smooth in the trivial sense — they interpolate without dropping frames — but they all use the same handful of default curves. Material's standard curve, Apple's spring approximations, and Bootstrap's ease-in-out are everywhere because nobody wants to derive a custom curve from scratch. Lea Verou's original cubic-bezier.com from 2011 still remains the canonical reference for the visual editing pattern, and the four parameters of CSS easing functions on MDN haven't changed. What has changed is how cheap it is to design and ship a small set of branded curves: 30 minutes with this editor and a clear style guide, and you can retire ease-in-out across an entire app. The full timing model is specified in the CSS Easing Functions Module Level 1.

What is cubic-bezier()?

The CSS cubic-bezier() function defines an easing curve for transitions and animations. It takes four parameters — x1, y1, x2, y2 — representing two control points of a cubic Bezier curve. The curve starts at (0, 0) and ends at (1, 1), where the x-axis represents time and the y-axis represents the animation progress. By adjusting the control points, you can create effects like overshoot (values above 1), slow starts, or bouncy endings.

Every CSS transition uses some form of easing. When you write transition: opacity 0.3s ease, the browser is actually applying cubic-bezier(0.25, 0.1, 0.25, 1.0) behind the scenes. The five built-in keywords — linear, ease, ease-in, ease-out, and ease-in-out — are just aliases for predefined cubic-bezier values. By writing your own cubic-bezier() function, you gain precise control over how an animation accelerates and decelerates, which is essential for crafting motion that feels intentional rather than generic.

The mathematics behind Bezier curves come from computer graphics, where they are used to define smooth parametric paths. In CSS, the curve is constrained so that the x-axis always moves forward in time (which is why x1 and x2 must be between 0 and 1), but the y-axis — representing output progress — can exceed those bounds. This means an animation can temporarily overshoot its final state before settling, creating a natural, spring-like feel that is difficult to achieve with simple linear interpolation.

How to use this tool

Drag the two control points on the graph or enter exact values in the number fields. The green control point (P2) determines the curve's ending behavior, while the purple control point (P1) controls the starting behavior. Select a preset from the dropdown to start from a known curve and modify it from there. Click "Play Animation" to see how a ball moves along the curve in real time. Adjust the duration slider to test different speeds and get a feel for how the curve performs at various animation lengths.

Copy the output in either direct CSS or CSS variable format using the copy buttons below the preview. The direct CSS output gives you a ready-to-paste transition-timing-function declaration, while the CSS variable format wraps the values in custom properties so you can manage your easing tokens from a single location. Use the "Copy Share URL" button to encode the current curve into the page URL, making it easy to share your custom easing with teammates or save it for later.

Practical examples

Button hover transition with overshoot effect

A subtle overshoot on button hover gives interactive elements a lively, tactile feel. The y2 value exceeding 1 makes the scale briefly go past the target before settling back, creating a micro-bounce that draws attention without being distracting.

.btn {
  transform: scale(1);
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.btn:hover {
  transform: scale(1.05);
}

Modal entrance animation (scale + fade)

When a modal dialog enters the screen, combining a scale transform with an opacity fade creates a polished entrance. Using an ease-out style curve — fast at the start, decelerating toward the end — makes the modal feel like it is arriving from somewhere and coming to rest naturally.

.modal-overlay {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),
              visibility 0.25s;
}

.modal-content {
  transform: scale(0.95) translateY(10px);
  opacity: 0;
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
              opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}

.modal-overlay.open {
  opacity: 1;
  visibility: visible;
}

.modal-overlay.open .modal-content {
  transform: scale(1) translateY(0);
  opacity: 1;
}

Dropdown menu slide-down with deceleration

Dropdown menus benefit from a curve that starts fast and slows down toward the end. This gives the impression of the menu quickly responding to the user's click and then gently easing into its final position, rather than abruptly stopping.

.dropdown-menu {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transform: translateY(-8px);
  transition: max-height 0.4s cubic-bezier(0.22, 1, 0.36, 1),
              opacity 0.3s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.dropdown.open .dropdown-menu {
  max-height: 400px;
  opacity: 1;
  transform: translateY(0);
}

Common patterns and best practices

When designing custom easing curves, keep these guidelines in mind to create animations that feel both polished and performant.

Browser Support

For developers working with newer CSS features, cubic-bezier() works seamlessly with the Web Animations API, the animation shorthand, individual transition properties, and the View Transitions API for page-level transitions. It remains the most universally supported easing method in CSS.

Common Pitfalls

FAQ

What's the difference between cubic-bezier and linear/ease?

Keywords like 'ease', 'linear', and 'ease-in-out' are shorthand for specific cubic-bezier values. For example, 'ease' is equivalent to cubic-bezier(0.25, 0.1, 0.25, 1.0). Using cubic-bezier() directly gives you full control to design a custom curve that isn't limited to these five presets.

Can I use values outside the 0-1 range?

The x-values (x1, x2) must stay between 0 and 1 because they represent time progression. However, the y-values (y1, y2) can go above 1 or below 0 — this creates an overshoot or anticipation effect where the animation temporarily exceeds its target value before settling.

How does cubic-bezier affect animation performance?

The cubic-bezier curve itself has no impact on rendering performance. The curve is pre-calculated by the browser before the animation starts, so changing the curve complexity does not add per-frame overhead. The performance cost comes from what you animate: transform and opacity are handled by the GPU compositor and are cheapest, while properties that trigger layout recalculation (width, height, margin) are expensive regardless of the easing function used.

What is the difference between cubic-bezier and steps()?

cubic-bezier() creates smooth, continuous curves where the animation progresses fluidly from start to finish. In contrast, steps() creates discrete frame jumps, dividing the animation into a fixed number of equal intervals with no interpolation between them. steps() is particularly useful for sprite sheet animations where you want to jump between frames, or for creating a typewriter effect. You can combine both in a single animation by using different timing functions on different keyframe segments.

How do I create a bounce effect?

Use y-values above 1 to make the animation overshoot its target before settling back. For example, cubic-bezier(0.34, 1.56, 0.64, 1) produces a noticeable bounce at the end of the animation. The higher the y-value, the more pronounced the overshoot. For a more complex multi-bounce effect, you would need to use CSS @keyframes with multiple percentage stops rather than a single cubic-bezier curve, since cubic-bezier can only produce one overshoot peak.

Can I use cubic-bezier with CSS custom properties?

You cannot store a cubic-bezier() function itself inside a CSS custom property and then use it as a timing function value, because the timing function must be a literal value that the parser can evaluate at declaration time. However, you can use custom properties for duration, delay, and other animation properties alongside a literal cubic-bezier() timing function. Some developers define their easing values as custom properties in a comment block or documentation for reference, then use the literal values in their actual transition declarations.

Related guides

Related tools