li直接加transition或animation无效,因默认可见无初始隐藏态;需CSS设opacity:0/transform并JS逐个添加类触发过渡,配合唯一key和挂载后执行确保动效生效。

直接给 li 加 transition 或 animation 不会生效——列表项没有“初始不可见”状态,浏览器不触发重排/重绘,动画根本不会启动。
为什么 li 直接写 animation 没反应
HTML 列表默认是可见且已渲染的,@keyframes 动画需要一个明确的“起始帧”(比如 opacity: 0、transform: translateY(20px))才能插值过渡。如果 DOM 渲染完才加动画类,浏览器会跳过初始态,直接显示最终效果。
- 常见现象:页面一打开,所有
li瞬间出现,毫无入场感 - 错误写法:
li { animation: fadeIn 0.4s; }—— 没定义起始状态,fadeIn里的from被忽略 - 正确前提:必须用 JS 控制显隐时机,或确保元素挂载时处于隐藏态(如通过
display: none+offsetHeight强制重排后再显)
怎么让每个 li 依次淡入+上滑
核心是「CSS 声明过渡 + JS 控制类添加时机」,避免用 nth-child 写死延迟(响应式或动态增删时失效)。
- 基础 CSS 只需两段:
li { opacity: 0; transform: translateY(16px); transition: opacity 0.35s ease, transform 0.35s ease; }li.is-entered { opacity: 1; transform: translateY(0); }- JS 添加类时逐个延迟(推荐用
setTimeout或requestAnimationFrame): listItems.forEach((el, i) => setTimeout(() => el.classList.add('is-entered'), i * 80));- 别用
display: none切换——它不支持 transition;可用visibility: hidden配合opacity保留布局占位
Vue/React 里列表动效为啥一闪而过
框架会复用 DOM 元素(尤其用索引当 key 时),导致 transition 类被快速覆盖或丢失,动画来不及播完。
立即学习“前端免费学习笔记(深入)”;
- Vue 必须用
<transition-group>,且每个li的key是稳定唯一 ID,不是:key="index" - React 推荐用
framer-motion的<motion.li>,它自动处理 layout motion 和 exit 逻辑 - 关键点:动效依赖 DOM 实际插入顺序,若列表由 API 异步加载,得等
mounted/useEffect完成、DOM 挂载后再批量添加类,否则offsetHeight读不到真实尺寸,延迟计算失准
最容易被忽略的是:动画节奏和 DOM 生命周期强耦合。哪怕 CSS 写对了,JS 添加类的时机差几毫秒,或者没强制重排,整个动效就废掉。别只调样式,先确认元素是否真的“从隐藏态开始过渡”。



















