I wanted a list where items rise and fade in one after another, the classic stagger. My first prompts hardcoded animation-delay per child, which breaks the moment the list length changes, and used a linear ease that felt mechanical.
The cleaner approach was to compute the delay from the item index with a CSS custom property set inline (--i) and calc(), so any number of items staggers automatically. Paired it with an ease-out curve and, of course, a reduced-motion branch that shows everything at once with no delay.
Works great. Wondering if nth-child delays are worth it over the --i variable for very long lists?
Animate a staggered entrance for a list of items in pure CSS. Requirements:
- Each `<li>` gets an inline `style="--i: N"` (0-based index). Delay is computed: `animation-delay: calc(var(--i) * 60ms)`. This must scale to ANY list length with no per-child rules and no JS.
- Keyframes animate `transform: translateY(12px) -> 0` and `opacity: 0 -> 1` only. No layout properties.
- Easing `cubic-bezier(0.16, 1, 0.3, 1)`, duration 420ms, `animation-fill-mode: both` so items start hidden and hold visible.
- Cap the total cascade: after index 12, clamp the delay so a 100-item list doesn't take 6 seconds. Use `calc(min(var(--i), 12) * 60ms)` and explain the clamp.
- `@media (prefers-reduced-motion: reduce)`: remove the animation and delay entirely; all items visible immediately.
Output the CSS plus a 5-item HTML sample showing the inline `--i`. Note why fill-mode:both prevents the flash-of-visible-then-hidden.