推荐用 transition 实现 li 进入动画:先设 opacity: 0 和 transform: translatey(20px),再通过 js 添加 is-visible 类触发过渡;依次延迟可用 js 动态设 transition-delay;框架中须用 transition-group 等专用组件避免 dom 复用导致失效。

怎么用 CSS 实现 li 元素的进入动画
直接给 li 加 animation 不会生效——因为列表项默认没有“初始不可见”状态,浏览器不会触发重排/重绘来触发动画。必须配合 JavaScript 控制显隐,或用 CSS 的 @keyframes + opacity/transform 配合 transition 在显隐切换时触发。
推荐做法:先让 li 处于 opacity: 0; transform: translateY(20px); 状态,再通过 JS 添加类(如 is-visible)触发过渡:
li {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
li.is-visible {
opacity: 1;
transform: translateY(0);
}
- 别用
display: none切换——它不支持 transition - 用
visibility: hidden可以保留布局,但依然要配opacity才有渐变效果 - 如果列表是动态渲染(比如 Vue/React),确保 DOM 挂载后再加类,否则动画可能跳过
如何让每个 li 动画依次延迟出现
靠 animation-delay 或 transition-delay 配合 :nth-child(n) 最直接。但注意:不能写 li:nth-child(1) { transition-delay: 0s; } 这种静态规则,得用循环生成或 CSS 自定义属性动态控制。
更稳妥的方式是 JS 动态设置 style:
document.querySelectorAll('li').forEach((el, i) => {
el.style.transitionDelay = `${i * 0.1}s`;
});
-
transition-delay只对首次显隐生效;再次隐藏再显示,需重置 class 或用animation配合animation-fill-mode: forwards - 用
for循环比forEach更易控制起始索引(比如跳过 headerli) - 移动端要注意,过多延迟叠加可能导致最后几项动画卡顿,建议总延迟不超过 1s
animation 和 transition 哪个更适合列表项动画
transition 更轻量、可控性更强,适合「显隐」这类二值状态切换;animation 更适合复杂路径(比如弹跳、旋转),但需要额外管理播放状态和重播逻辑。
- 用
transition:只需控制 class 开关,浏览器自动补间,内存占用低 - 用
animation:要写@keyframes,且每次重播需用animation-play-state或移除再添加 class 触发 - 如果列表会频繁增删(如搜索过滤),
transition+reflow更稳定;animation容易因 DOM 重用导致状态错乱
React/Vue 中列表动画为什么经常失效
根本原因是框架的 DOM 复用机制:相同 key 的 li 被复用时,class 变化可能不触发重排,或 transition 被跳过。Vue 的 <transition-group></transition-group>、React 的 react-transition-group 就是为解决这个而生。
- Vue 必须给
<transition-group></transition-group>加name,且内部li必须有唯一key,否则动画只在首项生效 - React 中不要直接在
map里写className={visible ? 'in' : 'out'},要用CSSTransition包裹单个li - 关键点:动画样式必须作用于被包裹的元素本身,而不是父容器——很多人把
transition写在ul上,结果没用
CSS 列表动画真正难的不是写法,而是判断什么时候该用 JS 控制、什么时候交给框架封装,以及如何避免 DOM 复用带来的状态残留——这些细节不排查,光抄代码永远只能动第一项。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











