sibling-index()
The sibling-index() css function returns an <integer> for the element's ordinal position among its parent's element children. It's 1-based, like :nth-child(): the first child returns 1, and the last returns the length of Element.children.
Syntax
<sibling-index()> = sibling-index()
It takes no arguments. The value is resolved per element, so a single rule gives every sibling a different <integer>.
The JS analogue
[...el.parentElement.children].indexOf(el) + 1
While JS reads once, CSS re-resolves live.
Uses cases
Math on position. Since it returns an integer (not a string), it composes with calc(), mod(), round():
/* alternating offset without :nth-child(odd) */
.card { translate: calc(mod(sibling-index(), 2) * 20px) 0; }
/* fan-out rotation */
.card { rotate: calc((sibling-index() - 3) * 5deg); }
Paired with sibling-count(). Position relative to total is where it gets expressive, normalizing to a 0→1 ratio lets you interpolate anything across a list:
.item {
--t: calc((sibling-index() - 1) / (sibling-count() - 1));
opacity: calc(1 - var(--t) * 0.6);
}
Note that counter() gives a similar result but returns a string, which suits generated content rather than calculation.
You can also use sibling-index() to apply dynamic styles, such as varying background colors based on the element’s index:
.menu-item { background-color: hsl(calc((sibling-index() - 1) * 90), 70%, 60%); }
Review relative colors