sibling-index() and sibling-count(): CSS finally knows which one it is
Firefox 154 brings these two functions to Baseline. They return the current element's position among its siblings and the total sibling count, so staggered animation, ordered colours, and even sizing can be computed in CSS instead of an inline variable per element.
Firefox 154 shipped support for sibling-index() and sibling-count(), which moves both functions to Baseline Newly available.
They do something small:
sibling-index()returns the current element’s position among its siblings, starting at 1sibling-count()returns the total number of sibling DOM elements in the parent container, including the element itself
Those two numbers used to be JavaScript-only.
How it used to be done
For “each card fades in one after another”, the standard recipe was:
<li style="--i: 0">…</li>
<li style="--i: 1">…</li>
<li style="--i: 2">…</li>
li {
animation-delay: calc(var(--i) * 60ms);
}
So every added element needs a hand-written --i, and missing one shifts the whole sequence. Templating languages need a loop variable; static sites have to keep the built output in sync with the source.
Now the inline style goes away:
li {
animation-delay: calc((sibling-index() - 1) * 60ms);
}
Mind the 1-based part — if you want the first element to have no delay, subtract one. Forget it and the first item waits 60ms, which reads as a small stutter.
Three places this genuinely helps
Staggered animation
As above. Adding an element no longer touches the stylesheet, and the order follows the DOM by construction.
Ordered colours
Spreading hues evenly around the wheel:
.swatch {
background: hsl(calc(sibling-index() * 360deg / sibling-count()) 70% 55%);
}
Change the number of elements and the palette recomputes. No palette variables to maintain.
Dividing available space
sibling-count() removes “I do not know how many there are” as an obstacle:
.bar {
width: calc(100% / sibling-count());
}
Flex and grid are usually the better tool — this one earns its keep where flex is not an option: absolutely positioned children, or cases needing an explicit width.
How this differs from existing selectors
CSS already had :nth-child(), :first-child, :last-child. The distinction:
:nth-child(3)is a selector — it decides which rule matches which element, and only then can you style itsibling-index()is a value — it returns a number that can go intocalc(), intohsl(), intoanimation-delay
The former says “the third one turns red”. The latter says “the Nth one’s delay is N × 60ms”. The latter used to require JavaScript or an inline variable.
Support
| Browser | Version |
|---|---|
| Chrome / Edge | 138 |
| Firefox | 154 |
| Safari | 26.2 |
All three have landed, hence Baseline Newly available — meaning “usable, but older browsers degrade”. Since these functions only affect appearance (delay, colour, width), degradation produces “everything appears at once / same colour / equal width” rather than a broken layout or an error. That makes them safe to adopt as progressive enhancement.
Where I land
These will not save you many lines. What they remove is a class of coupling that has always been maintained by convention:
“Which element this is” is an intrinsic property of the DOM, yet it had to be injected from outside by a build tool or a template variable. Injection means two places know the same fact, and two places drift — adding an element and forgetting to update --i is the textbook symptom.
Now the number is read straight from the DOM. One source of truth. Changes that turn an external convention into an internal query tend to be worth more for the bugs they delete than for the lines they save.

Comments
…