错位动画每次都要给每个元素单独写一行 delay——今天 CSS sibling-index() 用一行代码把它彻底原生化了
错位动画每次都要给每个元素单独写一行 delay——今天 CSS sibling-index() 用一行代码把它彻底原生化了。
这个函数是 CSS Values and Units Module Level 5 的一部分,Chrome 138+、Firefox 154+、Safari 26.2+ 都已支持,2026 年 8 月 18 日正式进入 Baseline newly available 行列。它不需要任何参数,用的时候直接写进 CSS 里就行。
它能做什么? sibling-index() 返回当前元素在父级所有子元素中的位置序号,从 1 开始数。第一个子元素返回 1,第二个返回 2,依此类推。
举一个最直接的例子——错位入场动画。以前你要这样写:
li:nth-child(1) { animation-delay: 0ms; }
li:nth-child(2) { animation-delay: 100ms; }
li:nth-child(3) { animation-delay: 200ms; }
/* 写到第 N 个 */
现在一行:
li {
animation-delay: calc(sibling-index() * 100ms);
}
添加或删除列表项时,delay 会自动重新计算,不需要改任何一行代码。
配合 sibling-count() 用更灵活。 如果你想让最后一个元素先动画、第一个元素最后动,来一个「反向错位」:
.card {
animation: fade-in 0.4s ease both;
animation-delay: calc((sibling-count() - sibling-index()) * 80ms);
}
最后一个元素算出来是 (N – N) × 80ms = 0ms,立即触发;第一个元素要等 (N-1) × 80ms 才动。
进阶玩法:radial 放射状布局。 配合 CSS 原生三角函数 sin() 和 cos(),可以纯 CSS 做出圆形排列,不需要任何 JS 算坐标:
.radial-item {
--angle: calc((360deg / sibling-count()) * sibling-index());
--radius: 120px;
position: absolute;
left: calc(50% + var(--radius) * cos(var(--angle)));
top: calc(50% + var(--radius) * sin(var(--angle)));
transform: rotate(calc(var(--angle) * -1));
}
六个子元素自动围成六边形,八个就是八边形,增删元素自动重新排列。
生产环境要注意什么?
一个是 Shadow DOM 作用域——sibling-index() 只认 shadow tree 里的兄弟元素,透进来的 light DOM 节点不算数。如果你在 Web Components 里用,要注意这个计数边界。
另一个是伪元素 ::before 和 ::after——它们不算 DOM 节点,不会被 sibling-index() 计入,但 sibling-index() 可以用在它们的样式声明里。
还有性能—— sibling-index() 和 sibling-count() 的值在 layout 时计算,输出是纯数字,可以直接进 calc(),不会触发额外的重排或重绘。
下一步怎么落地? 如果你项目里还在用 JS 动态注入 –index 变量给元素做错位动画,现在可以检查一下 caniuse.com/wf-sibling-count——全球约 82% 的浏览器已支持,主流项目可以逐步切过来了。先从列表组件的入场动画开始,用 @supports 做个渐进增强保底:
.reveal {
opacity: 1;
transform: translateY(0);
}
@supports (animation-timeline: scroll()) {
.reveal {
animation: fade-up ease-out both;
animation-delay: calc(sibling-index() * 80ms);
}
}
评论区
登录后可评论。