~/wiki / motion-i-animatsiya / printsipy-animatsii-easing-duration-delay

Easing, duration, delay: three parameters that make animation live, not cartoon

Main chat

A chat for vibe coders: news, guides, live cases, marketplace, and finding executors.

$ cd section/ $ join vibe dev
Easing, duration, delay: three parameters that make animation live, not cartoon - обложка

You can take the right type of animation, the right component, and still get something mechanical or cartoonish. Three parameters determine how much animation feels like real: easing, duration, delay.

Change any of the three and the same animation will look very different. The difference between “professional product” and “made over the weekend” is often just in these numbers.


Easing: how real objects move

Linear motion does not exist in nature. The ball is speeding up. The rolling ball is slowing down. The door opens quickly and slows down smoothly. In UI, transitions with easing curves always feel more natural because they behave like physical objects.

Six curves you need to know

ease-out - Fast start, smooth braking. The most natural for most UIs. It simulates an object that brakes when it stops. Use for incoming elements, appearing cards, toast.

**ease-in* - Slow start, acceleration to end The object picks up speed and disappears. Use for outgoing elements, closing modals, deleted list elements.

**ease-in-out* - slowing down on both sides. Transfer between states of one element. It feels like an object that is gaining and losing speed.

**linear* is a constant speed. Only for progress bars and rotational spinners. Everything else looks mechanical.

cubic-bezier(0.34, 1.56, 0.64, 1) - spring easing. Easy flight to the destination and return. It creates a sense of resilience and life. For the appearance of icons, success-animations, elements that need “liveliness”. Do not abuse - once on the screen.

cubic-bezier(0.16, 1, 0.3, 1) - ease-out expo. Very fast start, long smooth completion. Modern premium-feel. Use Linear, Vercel, Notion.

css
/* Входящие элементы — ease-out expo */
.card-enter {
  animation: slideUp 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

/* Уходящие элементы — ease-in */
.card-exit {
  animation: slideDown 0.25s cubic-bezier(0.4, 0, 1, 1) forwards;
}

/* Физика — spring с перелётом */
.button:active {
  transform: scale(0.97);
  transition: transform 0.1s cubic-bezier(0.34, 1.56, 0.64, 1);
}

Why easing is more important than duration

Interesting effect: ease-out with a duration of 350ms feels faster than linear with a duration of 250ms. Because most of the ease-out movement happens in the beginning – the user sees the result quickly. Proper easing is more important than short duration.

The practical consequence: if the animation seems slow, first check the easing, then reduce the duration.


Duration: How long does it last

The rule: the smaller the element, the faster the animation. The more important the action, the more noticeable the transition.

Тип анимации Duration
Tap/hover feedback 80–120мс
Микровзаимодействие 150–200мс
Показать/скрыть 200–300мс
Переход между экранами 300–400мс
Onboarding/storytelling 400–700мс

The most common mistake is one duration for everything. The button that responds to clicking for the same 300ms as the transition to a new page feels slowed down.

A button is a small element, important but not a page. 100-120ms. The modal window is a big element, a structural change. 250-300ms. The entire page is 350-400ms.

Check that the duration is correct: play the animation and record the time until you want to click further. If you want to click before the animation is over, it’s too long.


Delay and Stagger: Consistency Instead of Chaos

**Delay is a delay before launch. Used for sequence: one element must appear before the other.

**Stagger is an increasing delay for the band. Formula: delay = index × interval.

css
.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 60ms; }
.list-item:nth-child(3) { animation-delay: 120ms; }
.list-item:nth-child(4) { animation-delay: 180ms; }

/* Или через CSS custom property: */
.list-item {
  animation-delay: calc(var(--index) * 60ms);
}

** Stagger rules:**

  • 40–80ms between elements – standard range
  • More than 100ms - already noticeably slow for lists
  • Less than 30ms – almost does not count as stagger

For larger lists (20+ elements): diminishing stagger. The interval is reduced for later elements so that the latter does not appear seconds after the first:

javascript
// Stagger уменьшается с индексом
const delay = Math.min(index * 60, 400); // максимум 400мс

How to transfer animation parameters to the developer

The most common reason for loss of animation in handoff: the designer transmits “about like this” through the prototype Figma, the developer reproduces by eye.

What needs to be conveyed explicitly:

plaintext
Animation: the appearance of the card
- Duration: 350ms
- Easing: cubic-bezier(0.16, 1, 0.3, 1)
Transform: translateY(16px) → translateY(0)
- Opacity: 0 → 1
Trigger: when mounting a component
Stagger (if list): 70ms between cards

Numbers can not be “guessed by sensation” – you need to convey accurately. Five seconds on the record will save an hour of editing.


Prompt for Codex/Claude Code

markdown
Add appearance animations for components on the [path] page.

Parameters:
Cards: opacity 0→1, translateY 20px→0
- Duration: 400ms
- Easing: cubic-bezier(0.16, 1, 0.3, 1)
Stagger: 70ms between cards
Trigger: IntersectionObserver when an item enters a viewport
- prefers-reduced-motion: disable animation, show immediately

Do not use setTimeout for stagger - CSS animation-delay only
IntersectionObserver with different thresholds.
plaintext
Easing
Incoming - ease-out or cubic-bezier(0.16, 1, 0.3, 1)
● Leaving - ease-in
● No linear on UI elements (progress/spinner only)

Duration
● Tap/hover: 80-150ms
● Show / hide: 200-300ms
Screen transitions: 300–400ms

Stagger.
40–80ms between elements
● For long lists: diminishing stagger (no more than 400ms in total)
Prefers-reduced-motion: show immediately without delay

How easing affects product perception

The same product with different easing curves is perceived differently.

Linear easing in everything - the feeling of a cheap app. It's mechanical, like computer graphics in the '90s. Reason: The brain recognizes linear motion as unnatural.

easy-in-out everywhere - nice but slow. Every animation floats. This is often found in products that have “overdone with smoothness.”.

ease-out for incoming, ease-in for leaving is a professional standard. The movement feels physical. Elements “arrive” and “fly away,” not just appear and disappear.

That is why one of the first questions when assessing the motion quality of a product is “What easing is used?” This is a quick indicator of attention to detail.


Stagger: When to add when not to add

Stagger makes the appearance of a group of elements readable - but only if there are several elements and they are the same type. Three cases where stagger works well: a list of cards (3-12 pieces), navigation points when opening the menu, icons in the tulbar.

Three cases where stagger only interferes: two elements (the delay is too noticeable), heterogeneous elements (dagger creates the illusion of disconnection), a mobile with a slow connection (the user is already reading the first card, the rest have not yet appeared).

For mobile: stagger 40-50ms (not 70-80ms as for desktop). A smaller interval — faster the whole sequence — less of a “wait until it boots up.”.


How to Find the Right Numbers Fast

There is no universal answer to “what duration?” There's a method:

Start with 300ms for any animation. Play it back. It seems slow - reduced to 200ms. Still slow, 150ms. It seems too fast - 350ms.

Start with ease-out for everything. If the animation seems sharp at the end – ease-in-out. If you want to live, cubic-bezier(0.34, 1.56, 0.64, 1).

It's not a rigorous science -- it's an iteration. There are three or four ways to find the right feeling. With the experience of iterations becomes less.


Frequent errors when working with duration

One duration for the entire product. "We have 300ms everywhere" - the hover button feels slow, the screen transition feels fast. Different meanings are needed for different contexts.

Duration without easing. 200ms with linear looks worse than 300ms with ease-out. If the animation seems mechanical, change easing first, then duration.

**Stagger on two elements. ** If there are two elements, stagger only interferes. The 70ms delay between two cards is noticeable and perceived as a bug, not a design solution.

Too big stagger on long lists. 20 elements × 70ms = 1.4 seconds to the last. For long lists, use the reduced stagger or limit the total time to 400-500ms.

$ cd ../ ← back to Motion and animation