Why easing makes animation feel alive
Move a box from left to right at a constant speed and it looks mechanical, like a machine part. Let it start quickly and settle gently into place and it suddenly feels like an object with weight. The only thing that changed is the easing curve: how progress is spread out over time.
Progress versus time
Every animation has a progress value that goes from 0 (start) to 1 (end). Easing is a function that takes linear time and returns how far along the motion should be.
| Curve | Formula (p = time from 0 to 1) | Feels like |
|---|---|---|
| Linear | p |
A machine. Constant speed, abrupt start and stop |
| Ease in | p³ |
Something gathering speed, like falling |
| Ease out | 1 - (1 - p)³ |
Something arriving and settling |
| Ease in-out | 4p³ for the first half, then 1 - (-2p + 2)³ / 2 |
A deliberate move from A to B |
Which one to use
- Things entering the screen: ease out. They arrive fast and settle. This is the most useful curve by far, because the viewer's eye catches the movement early and the element is readable sooner.
- Things leaving the screen: ease in. They start slowly and accelerate away, so they don't distract at the end.
- Things moving from one place to another on screen: ease in-out. Both ends are gentle, so the move reads as intentional.
- Linear: almost never for movement. It works for things that should feel mechanical or continuous: a progress bar filling, a clock hand, a line being drawn at a steady pace.
Timing matters as much as the curve
The same curve feels different depending on how long it lasts and how elements are staggered:
A few rules of thumb from building animated explainers:
- Stagger entrances by 150 to 400 ms, in reading order. Everything appearing at once reads as a flash; one thing at a time reads as a story.
- Keep small entrances short, around 300 to 600 ms. Longer feels sluggish.
- Time motion to speech. In a narrated video, an element should appear just as the narrator mentions it.
- Combine properties. A fade plus a small 20 to 40 pixel rise looks far more polished than a fade alone.
In code
const EASING = {
linear: (p: number) => p,
easeIn: (p: number) => p * p * p,
easeOut: (p: number) => 1 - (1 - p) ** 3,
easeInOut: (p: number) => (p < 0.5 ? 4 * p * p * p : 1 - (-2 * p + 2) ** 3 / 2),
};
// Where an element is at time t, for a move from `from` to `to`:
const value = from + (to - from) * EASING.easeOut(progress);
These are cubic curves. CSS offers similar built-in curves (ease-in, ease-out, ease-in-out) defined with cubic-bezier(), whose exact shapes differ slightly but follow the same idea.
Earlier in this series: how a video editor works and rendering MP4 video in the browser.
Nobody