Tuesday, May 26, 2026Tech HubAboutContactAdvertiseNewsletter
Back to Home
Advanced Tree Counting: Mathematical Layouts With `sibling-index()` And `sibling-count()`

Advanced Tree Counting: Mathematical Layouts With `sibling-index()` And `sibling-count()`

Meet `sibling-index()` and `sibling-count()`. Staggered cascade effect in one line of CSS without `:nth-child()` rules or JS workarounds. Works for 5 items or 5,000.

B
Blizine Admin
·4 min read·0 views

Durgesh Pawar May 21, 2026 0 comments Advanced Tree Counting: Mathematical Layouts With sibling-index() And sibling-count() 11 min read CSS , Coding , Techniques Share on Twitter ,  LinkedIn About The Author Durgesh Rajubhai Pawar is a freelance developer dedicated to building high-performance, accessible web applications. He specializes in orchestrating complex … More about Durgesh ↬ Email Newsletter Your (smashing) email Weekly tips on front-end & UX . Trusted by 182,000+ folks. See User Testing Live SmashingConf Antwerp 2026 Celebrating 10 million developers How To Measure UX and Design Impact, 8h video + UX training How To Measure UX and Design Impact, 8h video + UX training Building Modern HTML Emails with Rémi Parmentier Custom Web Forms for Angular, React, & Vue. Your backend. Meet sibling-index() and sibling-count() . Staggered cascade effect in one line of CSS without :nth-child() rules or JS workarounds. Works for 5 items or 5,000. You know that thing where you have a grid of cards, and you want them to fade in one after another? That staggered cascade effect. Looks great. Should be simple. And yet every time I’ve built it, the implementation has made me feel like I’m doing something fundamentally stupid. See the Pen [Dynamic Staggered Animations with CSS sibling-index() [forked]](https://codepen.io/smashingmag/pen/zxowBog) by Durgesh . See the Pen Dynamic Staggered Animations with CSS sibling-index() [forked] by Durgesh . Because the options were always the same. Say you want staggered animation delays on a list of 10 items. You either wrote a Sass loop that spat out a dozen :nth-child() rules, each one hardcoding a --index variable for that specific position: /* One rule per item. Hope the list never grows. */ li:nth-child(1) { --idx: 1; } li:nth-child(2) { --idx: 2; } li:nth-child(3) { --idx: 3; } /* ... eight more of these ... */ li:nth-child(10) { --idx: 10; } li { animation-delay: calc(var(--idx) * 100ms); } Ten items. Ten rules. If the list grows to 50? You cap it and hope for the best, or set up a Sass loop that generates hundreds of selectors at build time. Engineers like Roman Komarov have come up with O(√N) strategies — legitimately clever stuff — but you still end up with 63 rules to cover 1,023 elements. Or you looped through elements in JavaScript and set inline styles. style="--index: 3" . Right there in the DOM. Works fine. Also spreads layout concerns across your scripts and quietly breaks six months later when someone refactors the component without realizing the CSS depends on a JavaScript-injected variable. Both approaches have always bugged me for the same reason: you’re telling the browser something it already knows . The browser built the DOM tree. It knows which element is the third child. It has the data. CSS just couldn’t access it. Well, now it can: li { animation-delay: calc(sibling-index() * 100ms); } One line. Works for 5 items or 5,000. No event listeners. No mut

📰Originally published at smashingmagazine.com

Comments