What separates premium motion from cheap motion isn't the effect itself but easing and duration: the element starts quickly and settles softly instead of moving at a constant speed like a conveyor belt. Ease-out usually fits elements entering the screen, ease-in fits elements leaving it, ease-in-out fits moving between two points, and most interface animations fall within 100–400 ms depending on distance and element size. To keep the whole product moving to one rhythm, the team fixes a few named durations and curves as design-system tokens.
After this you will be able to
- Read a cubic-bezier value and tell ease-in, ease-out or ease-in-out from the shape of the curve
- Choose a curve for the type of motion: entering, exiting, moving, following a gesture, infinite rotation
- Set duration by distance and element size, and make exits shorter than entrances
- Define a set of motion tokens — durations and curves — for a design system
Contents
Why linear motion looks mechanical
In the micro-animations lesson we covered why an interface needs motion at all. This is the next step: how to make that motion feel well crafted. The main tool is easing — the curve that describes how an element's speed changes from the start of an animation to its end. Without it (linear), the element moves at full speed from the very first frame and stops just as abruptly.
web.dev puts it simply: nothing in nature moves linearly from one point to another, which is why linear motion feels robotic. Apple's talk on spring animations shows why: a linear animation's velocity graph has a sharp jump at the start and at the end. The eye reads that jump as a jerk — and the interface starts to look like a cheap slideshow.
linearease-inease-outease-in-outspringEntering, leaving and moving: which curve to pick
The names are confusing at first: ease-out is used when something appears, ease-in when it leaves. Nielsen Norman Group explains the logic: ease-out on entry slows the element before it stops, so the eye can predict where it will land; ease-in on exit speeds the element up, so it feels like it is accelerating away off the screen.
An element appears: dialog, tooltip, menu
- Curve
- ease-out
- How it feels
- Fast response and a soft stop — the interface feels responsive
An element leaves the screen for good
- Curve
- ease-in
- How it feels
- Accelerates away — doesn't hold attention on something no longer needed
An element moves within the screen
- Curve
- ease-in-out
- How it feels
- Smooth start and smooth stop — like an object moved by hand
An element follows a finger or cursor
- Curve
- No curve, 1:1 with the gesture
- How it feels
- Any delay or smoothing here reads as lag
A loading spinner rotating endlessly
- Curve
- linear
- How it feels
- Even rotation — the one case where linear is right
cubic-bezier: what the curve shows
Any of the standard curves can be written as cubic-bezier — a function with four numbers. As MDN describes it, it's a graph where the horizontal axis is elapsed time and the vertical axis is progress along the path. The start (0, 0) and end (1, 1) are fixed, and the four numbers set two control points in between that pull the curve into shape.
- A steep rise at the start means a fast start; a flat stretch at the end means a soft stop. That's ease-out
- A flat start and a steep end mean a slow build-up and an abrupt finish — that's ease-in
- An S-shaped curve is ease-in-out: speed up, fast middle, slow down
- If a control point's second coordinate goes above 1 or below 0, the element overshoots the target and comes back — that's how CSS does a light "kick"
- The standard values are defined in the W3C specification: ease-in is cubic-bezier(0.42, 0, 1, 1), ease-out is cubic-bezier(0, 0, 0.58, 1), ease-in-out is cubic-bezier(0.42, 0, 0.58, 1)
The standard keywords are fairly mild. On InterLAB projects we usually tune our own, more pronounced entry curve — a sharp start and a long smooth tail: at the same duration the interface feels faster. The easiest place to tune it is the browser itself: in Chrome DevTools, any transition in the Styles pane has an Easing Editor where you can drag the control points and see the result immediately.
Springs: overshoot and damping
A spring animation isn't defined by a curve and a time but by physics: how stiff the spring is and how much friction damps it. In its WWDC 2023 talk, Apple simplifies the setup to two parameters — duration and bounce. With zero bounce you get smooth motion without overshoot; with positive bounce the element overshoots the target and oscillates around it a few times as the motion dies down.
The spring's main advantage isn't the bounce. It can pick up the velocity at which a person released an element with their finger and carry on without a jerk, and if the target changes halfway, it turns around smoothly. That's why springs became the default animation in SwiftUI. On the web a spring can be approximated with the CSS linear() function over a set of points (documented on MDN) — which is exactly how the spring lane in the demo above works.
A spring fits
- Dragging cards, swipes, sheets — the motion continues the gesture
- Animations that may be interrupted midway
- A small overshoot as a pleasant accent: a like, adding to cart
- Products with a playful, friendly character
A spring is too much
- Everything bounces: menus, buttons, text, dialogs
- Serious interfaces — finance, healthcare, CRM — where precision matters
- Frequent actions people repeat dozens of times a day
- Visible bounce on large blocks — the screen starts to shake
Duration: distance, size, entering and leaving
Nielsen Norman Group gives a range of 100–500 ms for most animations, with the exact value depending on how complex the change is and how far the element travels. Press Replay and see where, for you, the line falls between "instant", "smooth" and "I'm waiting".
100ms200ms300ms500ms1000ms~100 ms~100 ms
simple feedback: a checkbox, a toggle (NN/g)
200–300 ms200–300 ms
noticeable changes, such as a dialog appearing (NN/g)
up to 400 msup to 400 ms
large movements across a big screen (NN/g)
- The smaller the element and the shorter the path, the faster the motion: a tooltip next to the cursor and a full-screen side panel can't share one duration
- Make exits shorter than entrances: per NN/g, a dialog may take 300 ms to open and 200–250 ms to close
- The more often an action repeats, the shorter or subtler its animation — Apple's HIG advises against adding motion to frequent interactions
- Animation shouldn't block: if someone is already clicking ahead, the interface doesn't wait for the effect to finish
- Even small differences are felt: NN/g notes that going from 250 to 300 ms can feel very different
Motion tokens: one rhythm for the whole product
When every developer picks durations by eye, the product ends up with 180, 250, 320 and 600 ms and five different curves — and the interface starts to feel sloppy, even though nobody can say why. The fix is to agree on a small set of named values — tokens — and use only those, just like colors and spacing from the palette.
duration-fast
- Value
- 100 ms
- Used for
- Presses, toggles, hover
duration-base
- Value
- 200 ms
- Used for
- Tooltips, dropdowns, exits
duration-moderate
- Value
- 300 ms
- Used for
- Dialogs and panels appearing
duration-slow
- Value
- 400 ms
- Used for
- Large movements across the whole screen
ease-enter
- Value
- cubic-bezier(0, 0, 0.2, 1)
- Used for
- Entering: fast start, soft stop
ease-exit
- Value
- cubic-bezier(0.4, 0, 1, 1)
- Used for
- Leaving the screen: acceleration
ease-move
- Value
- cubic-bezier(0.4, 0, 0.2, 1)
- Used for
- Moving between points on screen
spring-soft
- Value
- a spring with almost no bounce
- Used for
- Gestures: swipes, dragging, sheets
In code it's a single line: transition: transform var(--duration-moderate) var(--ease-enter). On InterLAB projects motion tokens live next to colors and typefaces in the design system: the designer writes "enter — moderate, ease-enter" in the mockup, the developer uses exactly those values, and the "a bit faster?" debate happens once rather than on every screen.
Common mistakes and how to check motion
- Too slow: 600–800 ms animations on buttons and menus make the site feel sluggish
- Everything bounces: bounce on every element stops being charming by the second screen
- Different curves on one screen: the menu slides in with ease-out, the panel next to it moves linearly
- The same duration for a tooltip and for a full-screen panel
- Exits as long as entrances — a closed dialog still lingers in front of the eyes
- Animation can't be interrupted: buttons don't respond until the effect finishes
Slow it down
Open the Animations panel in Chrome DevTools: it records the page's animations and lets you replay them several times slower. In slow motion you can see jerks, overshoots and mismatched curves.
Fix the curve
Adjust the control points in the Easing Editor in the Styles pane, watch the result right away, and turn the value you land on into a token.
Check on a phone
Walk through the key flows on an inexpensive smartphone: what's smooth on a laptop can stutter on a weaker device.
Get fresh eyes
Ask a colleague who hasn't seen the mockup to open and close the menu five times. If they start waiting for the animation, it's too long.
Well-tuned motion only gets noticed when it's taken away: the interface instantly turns abrupt or sluggish.
Sources
- Nielsen Norman Group — Executing UX Animations: Duration and Motion Characteristics
- web.dev — The basics of easing
- web.dev — Choosing the right easing
- web.dev — Custom easing
- MDN — cubic-bezier()
- MDN — linear()
- W3C — CSS Easing Functions Level 2
- Apple — WWDC23: Animate with springs
- Apple Human Interface Guidelines — Motion
- Chrome DevTools — Inspect animations