CSS 原生函数 sibling-index() 与 sibling-count() 实战指南

CSS 新函数 sibling-index() 和 sibling-count() 可直接获取元素在父级中的位置与总数,告别 :nth-child() 硬编码和 JS 注入,一行代码实现动态交错动画。
从“笨拙”的交错动画说起
前端开发中,卡片网格的渐次淡入动画(Staggered Animation)是常见需求。以往实现时,开发者往往面临两难选择:要么用 Sass 循环生成大量 :nth-child() 规则,要么用 JavaScript 为每个元素注入内联样式变量。
这两种方案都存在问题。前者代码冗余,列表一旦增长就得重新生成规则;后者则把布局逻辑混入脚本,后续重构时极易因遗漏依赖而“静默崩溃”。
核心痛点在于:浏览器明明知道每个元素在 DOM 树中的位置,但 CSS 却无法直接读取这个信息。 现在,这个缺口终于被补上了。
新函数:让 CSS 直接“数数”
sibling-index() 和 sibling-count() 是 CSS Values and Units Module Level 5 规范(第 9 节)新增的函数,源自 CSSWG issue #4559 的长期讨论。它们无需参数,直接在样式表中使用:
sibling-index():返回当前元素在其父元素所有元素子节点中的位置(从 1 开始)。第一个子元素返回 1,第五个返回 5。文本节点、注释和空白字符会被自动忽略。sibling-count():返回父元素拥有的元素子节点总数,相当于 JavaScript 中element.parentElement.children.length的 CSS 版。
关键在于,这两个函数返回的是数值(<number>),而非字符串。这意味着它们可以自由参与 calc()、min()、max()、round() 甚至 sin()、cos() 等数学运算。例如:
li {
animation-delay: calc(sibling-index() * 100ms);
}
这一行代码即可实现动态交错延迟,无论是 5 个元素还是 5000 个元素都适用,无需事件监听、MutationObserver 或任何 JS 逻辑。
与 :nth-child() 的本质区别
容易混淆的是,:nth-child() 是选择器,用于匹配元素;而 sibling-index() 是函数,返回数值。前者决定“选谁”,后者提供“数据”。此外,counter() 虽也返回计数,但它是字符串,且只能用于伪元素的 content 属性,无法参与数学计算。
实用场景与价值
- 动态动画编排:除延迟外,还可配合
sin()实现波浪效果,或结合mod()创建周期性样式。 - 自适应布局:根据
sibling-count()自动调整网格列数或元素尺寸,例如在父元素只有 3 个子元素时采用特殊布局。 - 复杂表格与列表:为长列表自动生成斑马纹或分组样式,无需维护选择器列表。
对于组件库开发者、动画爱好者以及任何维护动态列表的前端工程师,这都是一项能显著简化代码、提升可维护性的新特性。
兼容性与展望
目前该特性仍处于规范草案阶段,主流浏览器尚未全面支持。但正如 CSS 其他新特性一样,提前了解其设计思路,有助于在未来的项目中平滑过渡。建议开发者关注 Can I Use 的更新,并在实验性项目中先行尝试。
告别硬编码,让 CSS 真正“感知”文档结构——这或许是布局描述向更智能方向迈出的一小步。
本文基于 Smashing Magazine 的公开内容,由 AI 辅助整理改写后发布。
原标题:Advanced Tree Counting: Mathematical Layouts With `sibling-index()` And `sibling-count()`
阅读原文