Staggered CSS Animations with sibling-index()
Staggered animations without nth-child hacks
Staggered list animations used to require manually setting --index on each :nth-child or counting in JavaScript. The sibling-index() function gives every element automatic awareness of its position.
/* Manual index per nth-child */li:nth-child(1) { --i: 0;}li:nth-child(2) { --i: 1;}li:nth-child(3) { --i: 2;}li:nth-child(4) { --i: 3;}/* … repeat for every item … */li { transition-delay: calc(0.1s * var(--i));} li { transition: opacity .25s ease, translate .25s ease; transition-delay: calc(0.1s * (sibling-index() - 1));} Browser Support
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Not ready for production without a fallback.
Automatic indexing
sibling-index() returns each element's 1-based position. No manual counting, no matter how many items.
Dynamic safe
Add or remove items and the stagger adapts automatically. The old nth-child approach breaks when the list changes.
Count siblings too
sibling-count() gives the total. Use both for radial layouts, equal distribution, and more.
How it works
The classic staggered animation technique required setting a custom property like --i on every :nth-child selector, then using calc(0.1s * var(--i)) for the delay. This was fragile: add a list item and you need another rule. Some developers set the index via inline styles or JavaScript instead, adding complexity.
The sibling-index() function returns a 1-based integer representing the element's position among its siblings. Use it directly in calc() for staggered delays, radial positioning, or any layout that depends on element order. Its companion sibling-count() returns the total number of siblings, enabling formulas like distributing items evenly around a circle.