demo · v138

Stagger orchestra

Four staggered animations on one page — pin-fall, rainbow chord, radial fan, numbered card grid — all driven by sibling-index() and sibling-count(). Add or remove items with the buttons and the entire choreography re-balances itself, without ever recomputing anything in JS.

Behind a flag in earlier builds. sibling-index() and sibling-count() ship unflagged in Chrome 138. If your browser doesn't support them the demo renders unstaggered and the colour hue collapses to one tone.
probing sibling-index()…

1 — Pin-fall · per-pin delay = sibling-index() × 60ms, duration tied to sibling-count()

2 — Rainbow chord · hue = (sibling-index() / sibling-count()) × 360deg, height linear with index

3 — Radial fan · rotation = ((i - 1) / (n - 1) − 0.5) × 120deg, dealt one card at a time

4 — Numbered grid · counter + sibling-count() shows live "n of N" without any JS

The pattern

li {
  --i: sibling-index();
  --n: sibling-count();

  animation-delay: calc(var(--i) * 60ms);                        /* stagger */
  --hue:          calc((var(--i) - 1) / var(--n) * 360deg);      /* per-child colour */
  --angle:        calc(((var(--i) - 1) / (var(--n) - 1) - 0.5)
                       * 120deg);                                 /* radial layout */
}

What's happening

  1. sibling-index() returns the element's 1-based position among its element siblings. sibling-count() returns the total.
  2. Both are live — adding or removing siblings invalidates the layout and the animation choreography re-runs.
  3. Used inside calc(), they replace the entire family of "per-child" things that used to need JS or :nth-child(N) { … } exhaustive lists.
  4. The radial fan would have been impossible to make responsive — you'd hardcode each angle for each n. Now adding the 9th card auto-rebalances the other 8.
  5. The "1 of 12" label is a CSS counter (counter-increment: cardno) plus sibling-count() exposed via a data attribute that JS sets once.

see also