CSS easing: cubic-bezier control points and steps() jump terms

Published: 2026-09-05

How CSS timing functions work—cubic-bezier control points, keyword aliases like ease-in-out, and steps() jump terms—so transitions and animations feel intentional.

Timing functions control how a CSS transition or animation progresses over its duration—not how long it lasts. Duration says “take 300ms”; the timing function says “ease out,” “snap in four steps,” or “overshoot then settle.” The two main authorable forms are cubic-bezier() and steps().

Where timing functions apply

You set them on:

Property Typical use
transition-timing-function Hover, focus, and layout transitions
animation-timing-function Keyframe animations (can vary per keyframe)

Keywords such as ease, linear, and ease-in-out are aliases for specific cubic-bezier curves. Custom motion almost always means writing (or generating) an explicit cubic-bezier(x1, y1, x2, y2) or a steps(…) value.

.button {
  transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.loader {
  animation: pulse 1.2s steps(4, jump-end) infinite;
}

cubic-bezier: four numbers, one curve

A cubic Bézier easing maps time (input, 0→1) to progress (output). CSS fixes the endpoints at (0, 0) and (1, 1). You supply two control points:

cubic-bezier(x1, y1, x2, y2)
Parameter Meaning Constraints
x1, x2 Horizontal position of each handle (along time) Must be in 0–1 (invalid otherwise)
y1, y2 Vertical position (along progress) Any number—can go below 0 or above 1

X must stay in range so time never runs backward. Y can overshoot: y > 1 or y < 0 produces “back” / bounce-style easings that briefly go past the end value and return—great for playful UI, risky for opacity or layout that should not leave the intended range.

Mental model: drag two handles on a unit square graph. Steep early slope → fast start (ease-in-ish). Flat early, steep late → slow start, snappy finish (ease-out-ish). Both handles mid-curve → soft acceleration and deceleration (ease-in-out).

Keyword aliases you already know

Keyword Rough cubic-bezier Feel
linear cubic-bezier(0, 0, 1, 1) Constant speed
ease cubic-bezier(0.25, 0.1, 0.25, 1) Slight ease-in, stronger ease-out (default for many transitions)
ease-in cubic-bezier(0.42, 0, 1, 1) Slow start
ease-out cubic-bezier(0, 0, 0.58, 1) Slow end
ease-in-out cubic-bezier(0.42, 0, 0.58, 1) Slow both ends

Design tools often emit “ease out back” style curves with y > 1 on one control point. Those are still plain cubic-bezier(…); there is no separate CSS keyword for “back.”

steps(): discrete jumps and jump terms

steps() divides the duration into equal time slices and jumps progress in N discrete holds—useful for sprite sheets, typewriter ticks, and stepped progress indicators.

Modern syntax:

steps(<integer>, <jump-term>?)

Legacy aliases start and end still work; prefer the jump-* terms for clarity:

Jump term Behavior (simplified)
jump-end (default) / end Hold the start value, jump at the end of each interval; lands on the final value at the end
jump-start / start Jump immediately at the start of each interval
jump-none N holds with no jump at either endpoint (needs careful N for a full 0→1 trip)
jump-both Jumps at both ends; N intervals between endpoint jumps
/* Four equal holds; classic “end” stepping */
animation-timing-function: steps(4, jump-end);

/* Same idea with the older alias */
animation-timing-function: steps(4, end);

Pick steps when continuous easing looks wrong (frame-by-frame art, metronome UI). Pick cubic-bezier when you want smooth acceleration. Mixing both in one product is normal: buttons ease; loading bars or pixel art step.

Pitfalls and tips

  • Invalid X. If x1 or x2 is outside 0–1, the declaration is invalid and the property falls back (often to ease). Clamp X when editing by hand or in a UI.
  • Overshoot and layout. Back/bounce curves with y outside 0–1 can briefly overflow overflow:hidden boxes or cause scrollbar flicker—preview on the real property (transform is usually safer than width/top).
  • Duration vs curve. A dramatic curve on a 50ms transition is invisible; a linear curve on 800ms feels sluggish. Tune both together.
  • animation-timing-function on keyframes. You can set different timing between keyframes; the rule on the element is the default between stops.
  • Reduced motion. Respect prefers-reduced-motion: shorten or disable non-essential motion even when the curve is perfect.
  • Tokens. Store full timing-function strings (--ease-out-back: cubic-bezier(…)) so transitions and animations share the same feel.

Why design easing locally

Easing presets and brand motion tokens are easy to paste into online curve editors. A client-side editor keeps those curves in your tab—same privacy habit as other LocalTools utilities (Why “local only” matters for developer tools).

Try it on LocalTools

Open the CSS animation timing editor:

  1. Choose cubic-bezier or steps.
  2. For curves: start from a preset (linear, ease family, or “back” variants) or drag the control-point handles; X stays clamped to 0–1.
  3. For steps: set the step count and jump direction (jump-end, jump-start, or legacy start / end).
  4. Toggle transition- vs animation-timing-function, replay the preview, then copy the CSS declaration.

Nothing is uploaded; the output updates as you edit.

Related reading

All learn articles