Command Palette

Search for a command to run...

Hectal
Shots in this scene
SHOT 5.1Intermediate ~22 min · shot 1 of 6

What an Easing Curve Is

In one line

An easing curve says how much of the move is done at each moment of the time. It does not change how long a move takes, but it decides where the fast and slow parts are, and so how the move feels.

0/6 · 0%

Think of it like this

Two drivers cover the same 200 metres in 10 seconds. One holds a steady speed the whole way. The other pulls away hard, then eases off and rolls to the line. Same distance, same time, very different journeys. An easing curve is the driving style.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

easing
The rule for how a move's speed changes over its duration. Also called a timing function.
progress
How much of the move is done, from 0 (at the start) to 1 (at the end). The easing turns elapsed time into progress.
slope
How steep the curve is at a moment. Steep means fast, flat means slow.
keyframe interval
The gap between two neighbouring keyframes. An easing set on the animation restarts in each interval.
timing function
The CSS name for an easing: transition-timing-function and animation-timing-function.

Step by step

01Race the five keywords

Run "Five easings, one second" and press Go. Pause, then step. At 250 ms the dots are at 50 px (linear), 81.7 px (ease), 18.7 px (ease-in), 75.6 px (ease-out) and 25.8 px (ease-in-out). All five meet at 200 px at 1000 ms.

02Find the halfway point

Step to 500 ms. linear and ease-in-out are both at exactly 100 px: ease-in-out is symmetrical, so half the time is half the distance. The others are not: ease is at 160.5 px, ease-in at 63.1 px. Click a track and read its graph: the S-shape for ease-in-out, the quick rise for ease-out.

03See the restart between keyframes

In "Easing between keyframes" press Go. The move has a keyframe at 50%. With ease-in-out on the animation the top dot is at 98 px at 450 ms and at 100 px at 500 ms: it nearly stops in the middle, then speeds up again. A whole-move ease-in-out would be at only 83 px at 450 ms.

04Read a track's graph

Click the ease-out track: a steep rise, then flat. Click ease-in-out: an S.

Try it yourself

  1. 1

    Change one lane to a custom curve

    In "Five easings, one second" change style="--e: ease" on the second lane to --e: cubic-bezier(0, 0, 1, 0). Press Go, pause, and click the track: the graph stays low, then climbs steeply at the end (0.125 of the way at 500 ms, 0.52 at 900 ms).

  2. 2

    Compare feeling with one number

    Replace the duration 1000ms with 300ms and press Go, pause at the first frame after the click, then press Step three times (50 ms). ease has already moved 44 px of 200; linear only 33 px. The curve that starts steeply gets there first.

  3. 3

    Look at the three odd durations

    In "Zero, tiny and huge durations" press Run all four. The 0 ms box moves at once and has no track, the 1 ms box has a track that ends before the next frame, and the one-hour box has a track you can scrub but never see move. A duration of 0 is a jump, not a transition.

Code & diagrams

Try it: interactive

The easing lab

Pick each keyword and press Play: watch the dot and the marker on the curve. Turn on Compare to run it beside linear. Find the point where the curve is steepest.

Five easings, one second

Five dots, the same 1000 ms and distance, five easings. The console prints each lane's computed timing function. Press Go, then pause and step to read the positions.

Press Run to see the page.
00:00.000
animations
0.00s0.10s0.20s0.30s0.40s0.50s0.60s0.70s0.80s0.90s

Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.

frames

Console

Nothing logged yet.

Expected console output

linear      linear
ease        ease
ease-in     ease-in
ease-out    ease-out
ease-in-out ease-in-out
Easing between keyframes

Both dots travel 200 px in 1000 ms and are at 100 px at 50%. The top one has ease-in-out on the animation, so it eases in every interval. The bottom one sets its easing inside the keyframes: linear, then ease-out. Press Go.

Press Run to see the page.
00:00.000
animations
0.00s0.10s0.20s0.30s0.40s0.50s0.60s0.70s0.80s0.90s

Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.

frames

Console

Nothing logged yet.

Expected console output

animations before the click: 0
Feel itPanel entrance

The Filters panel slides in over 300 ms in both versions. Which feels better?

A A

Press Run to see the page.

B B

Press Run to see the page.
Play both, then choose:
Zero, tiny and huge durations

Four transitions on four boxes: 0 ms, 1 ms, a negative duration and one hour. The console prints each one's computed duration and how many transition tracks the box has right after the change.

Press Run to see the page.
00:00.000
animations
0.00s0.10s0.20s0.30s0.40s0.50s0.60s0.70s0.80s0.90s

Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.

frames

Console

Nothing logged yet.

Expected console output

0ms       duration 0s      tracks 0
1ms       duration 0.001s  tracks 1
negative  duration 0s      tracks 0
one hour  duration 3600s   tracks 1

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Set the easing on the wrong state

In "Five easings, one second" move transition: transform 1000ms var(--e); from .lane i into the .lane.go i rule, and press Go twice, once a second after the first press.

terminal
$ Press Go, wait for the end, press Go again, and read the tracks
── what you'll see ──
Going out: the dot eases as set. Coming back: it snaps to the start in one frame, with no track.
Measured on a one-lane copy: 1000 ms after the second press the transform is `none` and the transition is idle.

Break #2

A negative duration

In "Zero, tiny and huge durations" the third row is -300ms. Press Run all four and read its console line.

terminal
$ Read the console line for the negative row
── what you'll see ──
negative duration 0s tracks 0
Measured: the whole declaration was dropped, so there is no transition and no error.

Myth vs fact

Myth

A longer duration makes an animation smoother.

Fact

Smoothness comes from frames being drawn on time (Phase 6). A longer duration only makes each frame's step smaller. A badly chosen curve at 600 ms still feels wrong.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    With animation-direction: reverse or alternate, the browser flips the curve on backward runs: an ease-in plays as an ease-out, because the backward run is the original played in reverse.

  • ▸

    A CSS transition reversed half-way uses a reversing-shortening factor: the return trip lasts only as long as the distance already travelled, and the curve is scaled to fit. That is why a transition interrupted near its start comes back quickly.

Remember this

  1. 1

    The problem this solves: a move at one steady speed looks mechanical, because nothing in the real world starts and stops instantly. Things speed up and slow down. You need a way to say how, for every animation, without writing a frame-by-frame script.

  2. 2

    Time in, progress out. An easing function takes the fraction of time that has passed (0 at the start, 1 at the end) and returns the fraction of the move that is done (also 0 to 1). The browser then mixes the start and end values by that second number. For a move of 200 px, a progress of 0.25 means 50 px.

  3. 3

    The five keywords. linear returns the time fraction unchanged: equal distance each frame. ease (the default for CSS transitions and keyframe animations) starts fast and slows a lot at the end. ease-in starts slowly and ends fast. ease-out starts fast and ends slowly. ease-in-out is slow at both ends. The widget draws each one; the first example runs all five at once.

  4. 4

    Read the slope. Draw time across and progress up. Where the curve is steep, the thing moves fast. Where it is flat, it barely moves. ease-out is steep at the start and flat at the end, so the thing arrives quickly and settles. If you remember one thing from this topic: steep means fast.

  5. 5

    Where the easing applies. On a transition it covers the whole duration. In @keyframes an animation-timing-function on the element applies between each pair of keyframes, not across the whole animation, and it restarts in every gap. One written inside a keyframe replaces it for the gap that keyframe starts. The second example shows the near-stop this causes in the middle of a move.

  6. 6

    Same duration, different feeling. In the first example all five dots arrive at 1000 ms, yet at 250 ms ease is at 81.7 px of 200 and ease-in at 18.7. People judge speed by how soon something responds, so a curve that is quick at the start feels quicker for the same duration. The Web Animations API's default is linear, not ease: an animation written there without an easing moves evenly.

Explain it without notes

01

What does an easing function take in, and what does it return?

02

Why does ease-out feel faster than linear for the same duration?

03

Where does an animation-timing-function apply in an animation with several keyframes?

Practice

01

Make the second lane of "Five easings, one second" use ease-out over 400 ms and the third ease-in over 400 ms, then read the positions at 200 ms.

02

At 250 ms of a 1000 ms, 200 px move, which is ahead, ease or ease-in, and by how many pixels?

Done when you can

  • You can say what an easing takes in and returns

  • You can read a curve: steep is fast, flat is slow

  • You can name the five keywords, and which is the default for CSS and which for WAAPI

  • You know that a keyframe easing restarts in every interval

  • You know that zero and negative durations make no transition