Oh MyUtils

CSS Cubic Bezier Generator - Create Easing Functions Online

Create custom CSS easing curves with an interactive visual editor. Drag control points, preview animations, and copy the cubic-bezier() code.

Frequently Asked Questions

What is a CSS cubic-bezier() function?

The CSS cubic-bezier() function defines a cubic Bezier easing curve that controls the pace of CSS transitions and animations. It takes four numeric parameters — cubic-bezier(x1, y1, x2, y2) — which define two control points (P1 and P2) on a curve where the X-axis represents time progress (0 to 1) and the Y-axis represents animation progress (0 to 1). The start point P0 is always (0,0) and the end point P3 is always (1,1). By adjusting the control points, you determine how the animation accelerates, decelerates, or overshoots.

How do I use this cubic-bezier generator?

Drag the two control point handles (P1 and P2) on the interactive graph to shape your desired easing curve, or enter precise numeric values in the X1, Y1, X2, Y2 input fields. Watch the animation preview update in real-time. Optionally select a preset easing from the library as a starting point. Toggle Compare with Linear to see how your curve differs from constant-speed motion. Change the animation type (Translate, Scale, Opacity, Rotate) to test on different properties. Copy the generated CSS code using the copy button.

Is my data secure? Does anything get sent to a server?

Yes, your data is completely secure. This tool runs entirely in your browser using client-side JavaScript. No bezier values, animation settings, or any data whatsoever is sent to any server. All curve calculations, animation rendering, and code generation happen locally on your device. You can safely use it for proprietary design system work.

What do the X and Y values mean in cubic-bezier()?

The four values define two control points on a 2D graph. The X values (x1 and x2) represent points along the time axis and must be between 0 and 1. The Y values (y1 and y2) represent points along the progress axis and can be any number. When Y values are between 0 and 1, the animation progresses normally. When Y values go below 0 or above 1, the animation temporarily overshoots or undershoots the target state before settling, creating bounce or elastic effects.

What is the difference between ease, ease-in, ease-out, and ease-in-out?

These are named CSS keywords that correspond to specific cubic-bezier values. ease (0.25, 0.1, 0.25, 1) starts slightly slow, accelerates quickly, then decelerates smoothly — it is the default for CSS transitions. ease-in (0.42, 0, 1, 1) starts slow and accelerates, useful for elements leaving the screen. ease-out (0, 0, 0.58, 1) starts fast and decelerates, ideal for elements entering the screen. ease-in-out (0.42, 0, 0.58, 1) starts slow, speeds up in the middle, then slows down.

How do I create overshoot or bounce effects?

Set Y values (y1 or y2) outside the [0, 1] range. For an overshoot at the end (element goes past the target, then settles back), set y2 greater than 1, for example cubic-bezier(0.34, 1.56, 0.64, 1). For an undershoot at the start (element briefly moves backward before animating forward), set y1 less than 0. The generator's graph visually extends beyond the 0-1 box to show these overshoot zones.

Which easing curve should I use for my animation?

The best easing depends on the animation context. For UI entrances (modals, dropdowns appearing), use ease-out or a Quart/Quint Out curve for natural deceleration. For UI exits (elements disappearing), use ease-in for smooth acceleration away. For state changes (color shifts, size adjustments), ease-in-out provides balanced acceleration. For playful interactions (button feedback, micro-interactions), use a Back Out curve for subtle overshoot. Avoid linear for most UI animations as it feels mechanical.

Code Examples

function evaluateBezier(t, p0, p1, p2, p3) {
  const u = 1 - t;
  return u * u * u * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t * p3;
}

function cubicBezierY(x, x1, y1, x2, y2) {
  if (x <= 0) return 0;
  if (x >= 1) return 1;
  let low = 0, high = 1, mid;
  for (let i = 0; i < 20; i++) {
    mid = (low + high) / 2;
    const cx = evaluateBezier(mid, 0, x1, x2, 1);
    if (Math.abs(cx - x) < 0.0001) break;
    cx < x ? (low = mid) : (high = mid);
  }
  return evaluateBezier((low + high) / 2, 0, y1, y2, 1);
}

function formatCubicBezier(x1, y1, x2, y2) {
  const r = (n) => Math.round(n * 100) / 100;
  return `cubic-bezier(${r(x1)}, ${r(y1)}, ${r(x2)}, ${r(y2)})`;
}

console.log(formatCubicBezier(0.25, 0.1, 0.25, 1));
// cubic-bezier(0.25, 0.1, 0.25, 1)

// Animate using the bezier curve
function animate(x1, y1, x2, y2, durationMs, onProgress) {
  const start = performance.now();
  function tick(now) {
    const t = Math.min((now - start) / durationMs, 1);
    onProgress(cubicBezierY(t, x1, y1, x2, y2));
    if (t < 1) requestAnimationFrame(tick);
  }
  requestAnimationFrame(tick);
}

Related Tools