Easing
12 minEasing
Every CSS transition ships with a default easing curve: ease. It's a reasonable default and almost never the right choice. Understanding why requires understanding what easing curves actually encode—and why the wrong curve makes an interface feel sluggish even when the duration is identical.
An easing curve maps time to progress. A linear curve means the animation moves at constant speed. A curve that starts steep and flattens means the animation starts fast and decelerates. The shape of that curve is the difference between an interface that feels responsive and one that feels like it's wading through mud.
Why ease-in feels wrong
The single most important easing rule in UI: never use ease-in for entrances.
An ease-in curve starts slow and accelerates. In the physical world, this is how objects behave when gravity pulls them—they gain speed over time. But in a UI, the moment a user triggers an action, they expect immediate visual feedback. An element that starts moving slowly after a click feels broken. The user's mental model is: "I pressed the button; something should happen now."
Ease-in violates that expectation. The first 100–200 milliseconds of the animation show almost no movement, creating a perceptible lag between intent and response. By the time the animation reaches full speed, the user has already registered the delay.
This is why ease-out (fast start, slow finish) is the correct default for most UI transitions. The element responds instantly to user input—satisfying the expectation of immediacy—then decelerates into its final position, giving the eye time to track the movement and the brain time to register the new state.
The three named curves
Rather than memorizing arbitrary cubic-bezier values, it helps to think in terms of three named curves, each mapped to a specific interaction pattern:
Enter (ease-out)
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
Used when an element appears or moves into view in response to user action. Tooltips, popovers, dropdown menus, modals—anything the user triggered. The fast start confirms the action; the slow finish settles the element into place.
Move (ease-in-out)
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
Used when an element changes position without entering or leaving—a tab indicator sliding, a sidebar resizing, a list item reordering. Both the start and end need to feel smooth because the user is watching the entire trajectory, not just the endpoint.
Exit (ease-in)
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
Used when an element leaves the screen. Here, and only here, ease-in is appropriate. The element starts slowly—giving the user a moment to register that it's leaving—then accelerates off-screen. The slow start prevents the jarring "pop" of an element vanishing instantly. The fast finish gets it out of the way before the user loses patience.
Notice the asymmetry: entrances decelerate, exits accelerate. This is enter-slow, exit-fast—one of the most reliable motion heuristics in interface design.
Custom curves vs. browser defaults
The browser's built-in keywords map to these cubic-bezier values:
| Keyword | cubic-bezier | Use case |
|---|---|---|
| linear | (0, 0, 1, 1) | Color fades, opacity changes, progress bars |
| ease | (0.25, 0.1, 0.25, 1) | Generic default—rarely optimal |
| ease-in | (0.42, 0, 1, 1) | Exits only |
| ease-out | (0, 0, 0.58, 1) | Entrances |
| ease-in-out | (0.42, 0, 0.58, 1) | Symmetric moves |
The built-in ease-out and ease-in-out are serviceable but conservative. Their curves are relatively gentle—they don't commit strongly to the fast-start or slow-finish behavior that makes motion feel decisive. The custom curves listed in the named-curve section above have more pronounced acceleration and deceleration, which produces snappier, more intentional-feeling transitions.
Use the browser keywords for prototyping. Replace them with explicit cubic-bezier values before shipping. The difference is subtle in isolation and significant across an entire interface.
When to skip easing entirely
Not everything should ease. Opacity changes, color transitions, and background-color shifts often work best with linear timing. These properties don't involve spatial movement—there's no position for the eye to track—so the deceleration curve that feels natural for a sliding panel just adds unnecessary delay to a color fade.
Progress bars are another exception. A progress bar with easing looks dishonest—it appears to slow down near completion, suggesting the process is stalling. Linear motion accurately represents steady progress.
The rule: use easing for spatial motion, use linear for non-spatial property changes. When in doubt, apply ease-out. It is almost never the wrong answer for an entrance, and it is the single highest-leverage default you can set in your animation system.