Stagger, but never block

Offset entrances 30–80ms per item; every item is clickable at once.

From find-animation-opportunities, group entrances.

All at once vs. a sequence

Press Replay, then drag the stagger.

All at onceBad
animation-delay: 0ms300ms
StaggeredGood
calc(var(--i) * 50ms)650ms
.grid > * {
  animation: enter 300ms var(--ease-out) backwards;
  animation-delay: min(calc(var(--i) * 50ms), 400ms);
}
@keyframes enter { from { opacity: 0; transform: translateY(8px); } }

Click before it lands

Press Replay, then click card 12 right away.

Waits for the cascadeBad
Live from frame oneGood
.card { animation: enter 300ms var(--ease-out) backwards; }

/* Bad */
.card.entering { pointer-events: none; }

Stagger arrival, not typing

Type in the filter and compare the lists.

10 vendors
Replays per keystrokeBad
    cascades: 0
    Once, on arrivalGood
      cascades: 0
      input.addEventListener("input", () => {
        list.classList.remove("entering");
        for (const row of rows) row.hidden = !matches(row, input.value);
      });

      Why it matters, pros and cons

      Why it matters

      A 30–80ms offset makes a flash a sequence. It is decoration: never gate input.

      Pros

      • Gives dense grids a reading order.
      • One custom property per item.
      • Masks uneven data arrival.

      Cons

      • Pages seen daily: the cascade becomes a wait.
      • Long lists: cap the total delay.
      • Typing, sorting, paging are interactions, not arrivals.