Easings

An easing is the speed profile of an animation: how fast it starts, how it changes along the way, and how it settles. Duration says how long a menu takes to open. Easing says whether it feels like it opened for you or opened at you.

The two menus below use the same 250ms. Open them.

Ease in
Ease out

The left one eases in. It starts slow and hits full speed at the very end, so the menu seems to hesitate and then slam into place. The right one eases out. It starts at full speed and slows as it lands, which is the shape of almost every physical thing coming to rest.

Ease-out is the default for anything that appears in response to the user. You clicked, so the interface should move right away, then compose itself. Ease-in makes the user wait for the slow start, and there is almost no place in an interface where that is what you want.

Reading a curve

The graph shows time going left to right and progress going bottom to top. The dot on the curve and the ball on the track run on the same clock, slowed down to one second so you can watch it.

Linear is a straight diagonal: same speed the whole way, which reads as mechanical. Ease in bends toward the bottom, ease out bends toward the top. In-out does both, and suits things that move from one place to another on screen rather than things that appear.

Stronger than the defaults

The browser's built-in ease-out is mild. Its steepest part is not that steep, so the motion looks a little soft. A custom curve with a faster start and a longer tail makes the same 250ms feel quicker without changing the number.

ease-out
cubic-bezier(0.23, 1, 0.32, 1)

Both of these are ease-out curves. The right one, cubic-bezier(0.23, 1, 0.32, 1), covers most of the distance in the first third and spends the rest settling. Once you have used it for a while, the built-in one starts to look like it is dragging.

Springs are the other option. They are not a curve at all but a simulation, which is why they can be interrupted mid-flight. The interruptibility article covers them.

Usage

app.tsx
<div class="transition-[opacity,transform] duration-200 ease-(--ease-out)">
    ...
</div>
:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
}

.menu {
  transition:
    opacity 200ms var(--ease-out),
    transform 200ms var(--ease-out);
}

Put the curves in variables and use the same two or three across the whole product. Consistent easing does more for a cohesive feel than any single animation does on its own.

Resources

Search concepts

Search for a command to run...