How fast UI animations should be

Sep 18, 2026 · Motion · 3 min read

Good motion is mostly about restraint. An animation that is lovely the first time is irritating by the twentieth, and some interactions happen hundreds of times a day. The single most useful rule I know is this: the more often something happens, the less it should animate.

Give buttons a little when pressed

A button that does nothing visible between press and release feels dead, especially when the action takes a moment. A small scale on :active tells the hand that the press landed.

Not recommended
Recommended
.button {
  transition: scale 150ms ease-out;
}
.button:active {
  scale: 0.97;
}

Stay between 0.95 and 0.98. Smaller than that and the button looks like it is collapsing. Use the standalone scale property instead of transform: scale(), so the press never overwrites a transform the component already uses for positioning.

Hover should be close to instant

A hover effect answers the question "can I click this?" The answer is needed now, not in half a second. Keep hover color changes at 150ms or less, and consider no transition at all for dense lists where the pointer sweeps across many rows.

Not recommended
Recommended

Context menus, dropdowns and command palettes are opened constantly by people who already know what they want. An entrance animation there is a delay you charge them every time. Show the menu immediately and only animate the exit, which covers the jump without slowing anyone down.

Right-click in each area
Enter and exit
Not recommended
Exit only
Recommended
.menu {
  opacity: 1;
  transition: none; /* opening is immediate */
}
.menu[data-closing] {
  opacity: 0;
  transition: opacity 120ms ease-out;
}

Nothing moves on page load

If a toast slides in, a list staggers up or a counter rolls every time the page renders, then every refresh, every back button and every route change replays it. That is not delight; it is noise, and it makes the interface feel slower than it is.

Draft saved
Not recommended
Draft saved
Recommended

Animate in response to something the person did. In React with Motion, initial={false} renders the first state without animating, and only later changes transition:

<AnimatePresence initial={false}>
  {items.map((item) => (
    <motion.li key={item.id} exit={{ opacity: 0 }} />
  ))}
</AnimatePresence>

A quick timing guide

  • Hover and focus feedback: 0 to 150ms.
  • Press feedback: 100 to 200ms.
  • Small UI entering (tooltips, popovers): 150 to 250ms.
  • Larger surfaces (sheets, dialogs): 250 to 400ms.
  • Anything used many times a minute: as close to zero as you can get away with.

Checklist

  • Buttons scale to between 0.95 and 0.98 when pressed.
  • Hover transitions are 150ms or less.
  • Frequently used menus open instantly and animate only on close.
  • Nothing animates on first render unless it is the point of the page.
  • Motion respects prefers-reduced-motion.

This piece expands on the Motion rules in my cheat sheet, where every rule has a live example.

Keep readingAnimating entrances and exitsWhere things should grow from, why leaving should be quieter than arriving, and how to bring content in without it feeling heavy.