Cubic bezier

큐빅 베지어

A four-number function that shapes an easing curve from two control points — written as cubic-bezier(x1, y1, x2, y2).

Also known as: cubic-bezier()Bezier easing curve
···
html
<div class="wrap">
  <svg class="graph" viewBox="-15 -70 130 185">
    <path class="grid" d="M0,100 L100,100 M0,0 L0,100"/>
    <path id="curve" class="curve" d=""/>
    <line id="l1" class="cpline"/><line id="l2" class="cpline"/>
    <circle id="cp1" class="cp" r="2.6"/><circle id="cp2" class="cp" r="2.6"/>
    <circle id="tracer" class="tracer" r="3"/>
  </svg>
  <div class="track"><i id="ball" class="ball"></i></div>
  <code class="label">cubic-bezier(.34, 1.56, .64, 1)</code>
</div>
css
.wrap{position:absolute;inset:8% 10%;display:grid;grid-template-rows:1fr auto auto;gap:12px}
.graph{display:block;width:100%;height:100%;min-height:0}
.grid{stroke:var(--line);stroke-width:1;fill:none}
.curve{stroke:var(--accent);stroke-width:2.5;fill:none}
.cpline{stroke:var(--muted);stroke-width:.8;stroke-dasharray:2 2}
.cp{fill:var(--accent-2)}
.tracer{fill:var(--accent-3)}
.track{position:relative;height:10px;border-radius:6px;background:var(--line)}
.ball{position:absolute;top:50%;left:0;width:16px;height:16px;margin-top:-8px;border-radius:50%;background:var(--accent-3);box-shadow:0 2px 6px rgba(0,0,0,.25)}
.label{font:11px/1 ui-monospace,monospace;color:var(--muted);text-align:center}
js
const P1 = [.34, 1.56], P2 = [.64, 1];
const curve = document.getElementById('curve');
const cp1 = document.getElementById('cp1'), cp2 = document.getElementById('cp2');
const l1 = document.getElementById('l1'), l2 = document.getElementById('l2');
const tracer = document.getElementById('tracer');
const ball = document.getElementById('ball');
function toSvg(x, y) { return [x * 100, 100 - y * 100]; }
const p1s = toSvg(P1[0], P1[1]), p2s = toSvg(P2[0], P2[1]);
curve.setAttribute('d', 'M0,100 C' + p1s[0] + ',' + p1s[1] + ' ' + p2s[0] + ',' + p2s[1] + ' 100,0');
cp1.setAttribute('cx', p1s[0]); cp1.setAttribute('cy', p1s[1]);
cp2.setAttribute('cx', p2s[0]); cp2.setAttribute('cy', p2s[1]);
l1.setAttribute('x1', 0); l1.setAttribute('y1', 100); l1.setAttribute('x2', p1s[0]); l1.setAttribute('y2', p1s[1]);
l2.setAttribute('x1', 100); l2.setAttribute('y1', 0); l2.setAttribute('x2', p2s[0]); l2.setAttribute('y2', p2s[1]);

function bezier(t) {
  const x = 3 * (1 - t) ** 2 * t * P1[0] + 3 * (1 - t) * t ** 2 * P2[0] + t ** 3;
  const y = 3 * (1 - t) ** 2 * t * P1[1] + 3 * (1 - t) * t ** 2 * P2[1] + t ** 3;
  return [x, y];
}
const start = performance.now();
function loop(now) {
  const dur = 2200;
  const t = ((now - start) % dur) / dur;
  const pt = bezier(t);
  const s = toSvg(pt[0], pt[1]);
  tracer.setAttribute('cx', s[0]); tracer.setAttribute('cy', s[1]);
  const p = Math.max(0, Math.min(1, pt[1]));
  ball.style.left = 'calc(' + (p * 100) + '% - ' + (p * 16) + 'px)';
  requestAnimationFrame(loop);
}
requestAnimationFrame(loop);

The start (0,0) and end (1,1) are fixed; you move two control points (P1, P2) between them to shape the curve. The x-axis is time (0→1), the y-axis is progress (0→1). Pushing a control point's y outside 0–1 makes the curve overshoot the target and settle back — the back/elastic feel.

Many workflows draw the curve visually in a design tool and paste the numbers straight into CSS cubic-bezier(). Chrome DevTools' animation panel lets you edit the curve visually too.

The graph below is the curve itself; the bar underneath moves along that exact curve — fast where the curve is steep, slow where it's flat.

When to use

If a browser keyword (like ease-out) already works, use it. Reach for a custom bezier only when you're crafting a distinct brand feel.