Staggering animations across too many elements
Staggering 20+ list items 50ms apart creates a slow cascade the user has to wait through before they can interact with the page.
The wrong way
Applying a per-item delay to every card in a long list — the last card does not land until well after a second has passed.
{items.map((item, i) => (
<Card
key={item.id}
style={{
animationDelay: `${i * 60}ms`,
animation: 'fadeUp 200ms ease-out forwards',
}}
/>
))}
// 20 items × 60ms = 1,200ms before the last card landsWhy
Stagger is a tool for guiding the eye, not a default decoration. With a handful of elements, a brief cascade subtly directs attention to the last one to settle. With twenty, the cascade becomes a one-second wait the user did not ask for — and on a list that re-renders frequently (search results, filtered tables), it becomes a one-second wait every time they touch a filter. The motion budget is being spent on something that doesn't pay the user back.
The right way
Cap the stagger at the first five-or-so items, or skip the stagger entirely on long lists and cross-fade the whole group instead.
const MAX_STAGGER = 6;
{items.map((item, i) => (
<Card
key={item.id}
style={{
animationDelay: i < MAX_STAGGER ? `${i * 60}ms` : '0ms',
animation:
'fadeUp var(--motion-duration-normal) var(--motion-easing-enter) forwards',
}}
/>
))}