写过动画的人都踩过这个坑——每次写交错动画都要给每个 li 配 nth-child,今天这件事被两个 CSS 函数彻底原生化了
每次写列表的交错动画,都要给每个 li 配一行 nth-child,再算 delay——这件事今天被两个 CSS 函数彻底原生化了。
CSS Values and Units Module Level 5 定义了两个新函数:sibling-index() 返回元素在兄弟节点中的位置(从 1 开始),sibling-count() 返回同级兄弟的总数。它们从 2026 年 8 月 18 日正式进入 Baseline,Chrome 138+、Safari 26.2+、Firefox 154+ 支持,全球约 70% 覆盖率。
一个痛点被彻底填平
以前要实现列表的交错入场动画,通常有三个选择:给每个元素单独写一条 nth-child 规则,给 JS 遍历 DOM 设置 –index 自定义属性,或者装一个动画库。
以 5 个列表项为例,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; }
li:nth-child(5) { --i: 4; }
li {
transition-delay: calc(0.1s * var(--i));
}
如果列表长度变成 50 个,这套规则就要写 50 行。而且每次增删元素,都要同步改 CSS。
现在一个声明就搞定:
li {
animation: slide-in 0.5s ease-out forwards;
animation-delay: calc((sibling-index() - 1) * 120ms);
}
这个 -1 是关键:sibling-index() 从 1 开始计数,第一个元素的 delay 应该是 0 而不是 120ms。减 1 才能让第一个元素立即开始。
不只是动画
因为返回值是整数,calc() 能直接用,这两个函数的场景远不止 stagger 动画。
等分容器宽度——每个 tab 均分:
.tab {
width: calc(100% / sibling-count());
}
渐变色相:每个元素按位置分配不同的背景色:
.swatch {
background-color: hsl(
calc((360deg / sibling-count()) * sibling-index())
70% 50%
);
}
扇形布局:配合 CSS 三角函数把元素围成一圈:
.card {
--angle: calc((360deg / sibling-count()) * sibling-index());
transform: rotate(var(--angle)) translateY(-120px);
}
倒序 stagger:让最后一个元素先走:
.card {
animation: card-out 300ms ease both;
animation-delay: calc((sibling-count() - sibling-index()) * 80ms);
}
注意两个边界
第一,sibling-index() 和 sibling-count() 只统计直接子元素,不穿透 Shadow DOM。从 shadow-root 外部使用这两个函数会返回 0,这是浏览器的安全隔离,不是 bug。
第二,::before 和 ::after 不是真实 DOM 节点,不会被计入 sibling 数量,但可以反过来使用这两个函数——它们会基于原始元素的位置来计算。
渐进增强怎么做
Firefox 154 目前是 Preview support,部分场景可能不稳定。用 @supports 做回退:
.card {
animation: card-in 400ms ease both;
animation-delay: calc((sibling-index() - 1) * 120ms);
}
@supports (animation-delay: calc(sibling-index() * 1ms)) {
/* 这块在不支持的浏览器里会被跳过 */
}
不支持的浏览器会直接忽略不识别的 calc 表达式,fallback 到无 delay 的默认动画,不会破坏布局。
下一步
如果你的列表 stagger 动画还在靠 nth-child 规则或 JS 遍历,现在可以抽掉这段逻辑了。先在列表项上跑一行 animation-delay: calc((sibling-index() - 1) * 100ms),看看效果——如果列表长度固定,nth-child 还能接受;如果列表是动态的,这是必迁。
评论区
登录后可评论。