CSS sibling-index() staggers a whole list from a single animation-delay rule
CSS sibling-index() and sibling-count() became Baseline Newly available in August 2026, according to a dev.to post that tested them in Chrome 155. One calc() line now staggers a list, but hidden items still count.
The Engineer · Build desk
Key figures: the longest entry delay is 480 ms with the index capped at 8 and a 60ms step, whatever the list length. A 30th item waiting 1.8 seconds to appear, which the post says is not a feature. The capped test used a list of 12 items.
| Figure | Value | Note | Claim |
|---|---|---|---|
| Longest entry delay, index capped at 8, 60ms step | 480 ms | whatever the list length | 18 |
| A 30th item's wait to appear | 1.8 seconds | the post says this is not a feature | 17 |
| Items in the capped test | 12 items | 9 |
What happened
- The stagger becomes one rule: animation-delay set to calc(sibling-index() * 80ms), with the animation declared as fade-in 400ms backwards.
- In Chrome 155, a five-item list computed delays of 0.08s to 0.4s, and each item came out 120px wide in a 600px row.
- Capping the index with min(sibling-index(), 8) held the delay at 0.48s for items 9 to 12 of a 12-item list.
Why it matters
- constraint Hiding filtered items with display: none leaves their slots in the count. In the post's test, four visible items stayed 120px wide and left a 120px gap, so filter code has to remove nodes.
- decision Sites that still serve older browsers need a plain animation-delay declared on the line before the calc() one, because those browsers drop the whole declaration.
- capability A script that appends an item no longer renumbers anything. Delays and widths recomputed on the next frame after a sixth item was added.
The hand-numbered versions fail the same way. According to the post, both the nth-child ladder and the per-item `--i` style attribute break when the list grows, gets filtered, or gets a new item at the top [16]. The two functions remove the numbering [1]. Neither takes an argument, and both return integers, so they work inside `calc()`, `min()` and color functions [5]. Position counts from 1, like `:nth-child()` [2]. Only element children count, so text and comment nodes between them are ignored [3]. `sibling-count()` includes the element itself [4].
The post's objection to an uncapped stagger is concrete: a 30th item waiting 1.8 seconds [17]. Wrapping the index in `min(sibling-index(), 8)` at a 60ms step bounds the wait at 8 x 60 ms, or 480 ms [18]. We'd treat that cap as mandatory on any list a user can grow. The same functions order the exit: `(sibling-count() - sibling-index()) * 60ms` ran from 0.66s on the first item to 0s on the last in the 12-item test [10].
The one place the syntax misleads is the custom property. `li { --i: sibling-index(); }` looks like it stores the parent's position for its children [14]. It does not. An unregistered custom property keeps the literal text, and `var()` pastes that text into the child, where it runs against the child's own position [14]. A `<b>` that was the 4th child of the 3rd `<li>` came out 40px wide, not 30px [14]. With `calc(var(--i) * 10px)`, the 40px is the child's index of 4 and the 30px is the parent's index of 3 [19]. Registering the property with `syntax: "<integer>"` and `inherits: true` makes it compute on the `<li>` first and inherit the number, and the same `<b>` measured 30px [15].
Every value in the post comes from running the CSS in Chrome 155 [12]. The post says Firefox 154 completed engine support, which made both functions Baseline Newly available in August 2026 [21][20]. It reports no values from Firefox or any other engine. The 120px widths and the 0.48s plateau therefore describe one browser. They transfer only if the other engines count element children from 1 the same way Chrome does [2][3].
What to watch
- Whether Firefox 154 and the other engines reproduce the Chrome 155 figures, including the hidden-item count and the 40px versus 30px custom property result.
- When older browsers drop out of your support matrix, which is the point where the plain-value fallback line can be deleted.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence62
- Adoption
- Insufficient
- Hype gap+12
- Incentives
- Insufficient
- Confidence58
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
sibling-index() returns an element's position among its siblings and sibling-count() returns how many siblings there are, both as integers usable in calc().
- [2]
sibling-index() starts at 1, like :nth-child(), not at 0.
- [3]
Only element children count; text and comment nodes between them are ignored.
- [4]
sibling-count() includes the element itself.
- [5]
Neither function takes an argument. Both return an integer, so they work anywhere a number does, including inside calc(), min(), and color functions.
- [6]
The stagger becomes one rule: li { animation: fade-in 400ms backwards; animation-delay: calc(sibling-index() * 80ms); }.
- [7]
In Chrome 155, with five items in a 600px flex row using width: calc(100% / sibling-count()), the computed delays were 0.08s, 0.16s, 0.24s, 0.32s and 0.4s, and each item was 120px wide.
- [8]
Adding a sixth item with JavaScript made the next frame read delays of 0.08s through 0.48s at 100px each, with no observer and no re-render.
- [9]
With animation-delay: calc(min(sibling-index(), 8) * 60ms) and 12 items, entry delays climbed from 0.06s to 0.48s and stayed at 0.48s for items 9 to 12.
- [10]
With animation-delay: calc((sibling-count() - sibling-index()) * 60ms) on a .leaving class, the delays ran backwards from 0.66s on the first item to 0s on the last.
- [11]
Older browsers drop the whole declaration, so the post advises putting a plain animation-delay value (it shows 100ms) on the line before the calc() declaration.
- [12]
Every value in the post comes from running the CSS in Chrome 155.
- [13]
Hidden siblings still count because the count comes from the DOM, not from what is rendered. With one of five items set to display: none, the four visible items were still 120px each, leaving a 120px gap in a 600px row. The post says to remove filtered items from the DOM.
- [14]
An unregistered custom property --i: sibling-index() keeps the text sibling-index(), and var() pastes that text into the child, where it runs against the child's own position. A <b> that was the 4th child of the 3rd <li> came out 40px with width: calc(var(--i) * 10px), not 30px.
- [15]
Registering --i with @property, syntax "<integer>", inherits: true and initial-value: 0 makes it compute on the <li> first and then inherit the number; the same <b> measured 30px.
- [16]
Both the nth-child animation-delay ladder and hand-numbered --i style attributes break when the list grows, gets filtered, or gets a new item at the top.
- [17]
The post says a 30th item waiting 1.8 seconds to appear is not a feature.
- [18]
With the index capped at 8 and a 60ms step, the longest entry delay is 480 ms, whatever the list length.
- [19]
In the unregistered case the 40px width equals the child's own index (4) times 10px; in the registered case the 30px width equals the parent's index (3) times 10px.
- [20]
The post says both functions have been Baseline Newly available since August 2026.
- [21]
Firefox 154 completed the set of engines supporting the functions, which made both Baseline Newly available in August 2026.
Get this ledger inside ChatGPT. Ask about any of our stories and the answer brings its figure, each claim’s verdict and the sources. Free, no account.
Sources
1 independent publisher whose own reporting we read for this story.
- dev.toStop Hand-Numbering Staggered Animations. CSS sibling-index() Is Here
1 article · October 14, 2026
Topics and entities
Follow any of these and your For You feed starts watching them — no settings page required.