The curve is not the path
The commonest misreading of an easing curve is that it shows where something moves. It does not. It maps the animation's progress onto time.
Elapsed time runs along the bottom, from nought to one. How far through the change the element is runs up the side, also nought to one. A straight diagonal means the element moves at a constant rate for the whole duration. The bend is what makes movement read as natural, because nothing in the physical world starts and stops instantly.
Steepness is speed. Where the curve rises sharply, the element is moving fast; where it flattens, it has almost stopped. The [msm_tool slug="cubic-bezier-editor"] replays the motion beside the curve, which is the fastest way to connect the two.
Reading a curve at a glance
- Steep at the start, flat at the end. The element launches and settles — this is ease-out, and it is what most things arriving on screen should do.
- Flat at the start, steep at the end. Ease-in: a slow build then a rush. Right for things leaving, wrong for things arriving, because the user waits through the slow part.
- Flat at both ends. Ease-in-out. Smooth but slightly lifeless for short interface movements; better suited to longer transitions between states.
- A long flat tail. The commonest fault. The last part of the movement crawls, and the animation feels sluggish however short its total duration.
Arriving and leaving are different
An element entering the screen should decelerate into place. The user is about to look at it, and it should be still by the time their attention arrives.
An element being dismissed can accelerate away, because nobody is waiting to look at it. That asymmetry — ease-out coming in, ease-in going out — is one of the few motion rules that holds almost everywhere, and it costs nothing to apply.
Overshoot
The vertical axis may go above one, and that is what produces a bounce: the element passes its target and comes back. Push the second control point's vertical value past one to get it.
The horizontal axis cannot leave the nought-to-one range, because time does not run backwards. A curve that tries produces a shape the browser will not accept.
Overshoot is effective and easy to overdo. A small one — a few percent past the target — reads as physical. A large one reads as a toy, and on anything a person uses repeatedly it becomes tiring within a day.
Duration and curve are judged together
A pronounced curve at a long duration reads as slow rather than as characterful. Most interface motion sits between 150 and 300 milliseconds; below about 100 it is not perceived as motion at all, and above roughly 400 people start waiting.
Larger movements need slightly longer than small ones to feel like they travelled rather than teleported. A full-screen panel sliding in can take 300; a button changing colour should not.
The named keywords, and when they are enough
CSS ships with ease, ease-in, ease-out, ease-in-out and linear. Each is a cubic Bézier with fixed control points, and for a great deal of interface work they are entirely sufficient.
ease is the default and is a reasonable general choice. linear is usually wrong for movement — it is the one thing that never happens in the physical world — with one exception: continuous rotation, such as a loading spinner, where any easing produces a visible stutter each time round.
A custom curve earns its place when you want a specific character: a snappy launch, a gentle settle, an overshoot. If you cannot say what you want in those terms, a keyword will do.
Transitions and keyframes use it differently
On a transition, the curve applies across the whole change. On a keyframe animation, it applies between each pair of keyframes rather than across the sequence.
That catches people out: adding an ease to a three-keyframe animation eases three separate times, producing a stutter at each keyframe rather than one smooth arc. If you want a single curve across the whole thing, use two keyframes and let the curve do the shaping.
Respect reduced motion
Whatever curve you choose, wrap the animation in a check for the reader's motion preference. Vestibular disorders make large or repeated movement genuinely unpleasant, and honouring the system setting costs three lines:
@media (prefers-reduced-motion: reduce) { .thing { transition: none; } }
The setting exists because people asked for it. Overriding it because the animation is tasteful is not a judgement call anyone else has delegated to you.