transition-delay无法实现列表项自动级联进场,因其仅响应属性变化事件,不触发初始化动画;必须用animation-delay配合@keyframes,显式设置初始状态、递增延迟及animation-fill-mode: backwards。

不能用 transition-delay 实现真正的列表项级联进场——它只在状态变化时触发一次,且无法驱动初始化动画;必须改用 animation + animation-delay。
为什么 transition-delay 在列表进场中基本失效
常见错误是给 li 元素加 transition-delay 并期望页面加载后自动逐个淡入。但 transition-delay 不会主动启动,它只等待某个属性(比如 opacity)被 JS 或伪类修改时才生效。页面初始渲染时没有“变化事件”,所以整个列表静默显示,毫无动画。
-
transition是响应式机制:依赖 class 切换、:hover、JS 修改样式等显式触发 - 列表进场属于“初始化动效”,浏览器不会自动为初始值生成过渡帧
- 若强行用
display: none → block触发,transition会直接跳过(display不可过渡) - 即使用
visibility+opacity,也需先加一个初始隐藏 class,再用 JS 移除——这已脱离纯 CSS 自动化范畴
正确做法:用 animation-delay 配合 @keyframes
真正能实现“页面一打开就自动逐项入场”的,只有 animation。关键在于两件事:确保初始不可见、让每个 li 拥有独立延迟。
- 起始状态必须显式设为
opacity: 0; transform: translateY(10px);,并配合animation-fill-mode: backwards;,否则第一帧会闪现原样 - 每个
li的animation-delay要递增,例如li:nth-child(1) { animation-delay: 0s; },li:nth-child(2) { animation-delay: 0.1s; } - 避免手写十几次
nth-child,可用 SCSS@for $i from 1 through 10 { li:nth-child(#{$i}) { animation-delay: #{$i * 0.1}s; } } - 若列表长度动态(如 React 渲染),改用内联 style:
style={{ animationDelay: `${index * 0.1}s` }}
容易被忽略的兼容性与性能点
看似简单,但实际部署时几个细节常导致阶梯感断裂或首屏卡顿:
-
overflow: hidden父容器会裁切transform: translateY()的位移,导致部分列表项“进不来”,需检查父级是否意外设置了该样式 - 大量列表项(>50)同时应用
animation可能触发重排,建议结合IntersectionObserver,只对视口内元素启用动画 -
animation-timing-function推荐用cubic-bezier(0.25, 0.46, 0.45, 0.94)(类似ease-out),比默认ease更自然,避免“堆叠感” - 移动端 Safari 对
animation-delay小于0.05s的值可能四舍五入为 0,建议最小步长设为0.08s
真正麻烦的不是写几行 CSS,而是确认每个列表项是否始终参与渲染、初始状态是否被 backwards 正确捕获、以及父容器有没有偷偷吃掉位移空间——这些地方一漏,阶梯就塌了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











