最轻量且兼容性最好的做法是直接为每个子元素设置递增的transition-delay值,需统一初始状态、显式声明transition、避免父级继承,并在结构稳定时用:nth-of-type硬编码延迟。

用 transition-delay 控制子元素入场顺序
直接给每个子元素设置递增的 transition-delay 是最轻量、兼容性最好的做法。关键不是靠 JS 控制时机,而是让 CSS 自己按序触发——前提是所有子元素初始状态统一(比如都设为 opacity: 0; transform: translateY(20px);),且 hover 状态下同时切换为可见/就位。
常见错误是只写 transition: opacity 0.3s 却漏掉 delay,结果所有子元素“啪”一下全出来;或者把 delay 写在父容器上,对子元素无效。
- 子元素必须有独立的
transition声明(不能只靠父级继承) - 延迟值建议用
s单位,避免毫秒数难读(如0.1s、0.2s) - 如果子元素数量不固定,纯 CSS 难以动态计算 delay,此时需 JS 配合生成 style 或 class
配合 :hover + nth-child 实现免 JS 编排
当子元素结构稳定(比如固定 5 个 li),直接用 nth-child(n) 为每个位置硬编码 delay 最稳妥。不需要额外 class,也不依赖 JS 注入样式。
注意:nth-child 按 DOM 顺序计数,不是按渲染顺序;若中间有注释、文本节点或隐藏元素,可能错位。推荐用 nth-of-type 或确保子元素类型一致(如全是 div)。
ul:hover li:nth-of-type(1) { transition-delay: 0s; }
ul:hover li:nth-of-type(2) { transition-delay: 0.1s; }
ul:hover li:nth-of-type(3) { transition-delay: 0.2s; }
为什么不用 animation + @keyframes?
虽然能做出更复杂的入场动效(比如旋转+缩放),但 animation 默认不会随 hover 进出自动重播——需要加 animation-fill-mode: forwards 和 animation-play-state 切换,代码量翻倍,且 Safari 对 hover 中重置 animation 支持不稳定。
除非你明确需要非线性缓动(如 cubic-bezier(0.2, 0.8, 0.4, 1))或逐帧控制,否则 transition + delay 更可靠。
-
animation的delay是指动画开始前等待时间,和transition-delay含义一致,但触发逻辑不同 - 用
animation时,hover 离开后元素可能卡在终态,需额外写离开时的反向动画 - 移动端 touch 设备上,
:hover行为本身就有延迟或不触发,transition方案更易降级
实际项目中容易被忽略的细节
真正上线时,最常踩的坑不是写法,而是「过渡属性没覆盖全」和「初始状态不可见但占位」。
- 如果用了
transform入场,务必在初始状态也写transform: translateY(20px),否则第一次 hover 会从默认位置跳一下 - 别只设
opacity: 0就以为元素“消失”了——它仍占据文档流,要用visibility: hidden或height: 0; overflow: hidden配合 - IE11 不支持
transition-delay在伪类中动态生效(如:hover li:nth-child(2)),需降级为所有子元素统一 delay 或放弃 IE - 如果父容器设置了
overflow: hidden,而入场动画涉及超出边界的位移,记得给父容器加padding预留空间,否则会被裁掉
复杂点在于子元素样式彼此干扰,比如一个用了 transform,另一个用了 margin,它们的过渡节奏很难对齐。统一用 transform + opacity 是最省心的选择。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











