li元素无法直接对display:list-item做transition,应使用opacity、transform、max-height等可动画属性实现淡入、位移或展开效果,配合JS精确控制类名添加时机以确保动画触发。

list-item 本身不支持 transition
直接给 <li> 元素加 transition: all 0.3s 是无效的——因为 <li> 默认是 display: list-item,这个值无法被过渡。浏览器不支持在 list-item 和其他 display 值之间做平滑动画。
真正能过渡的,是它的「视觉表现属性」:比如 opacity、transform、height(需配合 overflow: hidden)、margin 等。关键在于:你得控制的是「可见性」或「位置/尺寸」,而不是 display 或 list-style 本身。
- 不要写
transition: display 0.3s—— 完全没反应 - 避免依赖
visibility单独过渡 —— 它不可动画,只能配合opacity用 - 如果要「逐项淡入」,得靠 JS 控制每个
<li>的 class 或 style,不能只靠 CSS
用 opacity + transform 实现入场动画
这是最常用也最稳妥的方式:保留 <li> 的文档流位置,只动透明度和位移。适合下拉菜单、加载后列表展示等场景。
示例结构:
立即学习“前端免费学习笔记(深入)”;
<ul class="fade-in-list"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul>
CSS 写法:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
.fade-in-list li {
opacity: 0;
transform: translateY(10px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
<p>.fade-in-list li.show {
opacity: 1;
transform: translateY(0);
}- 初始状态必须显式设
opacity: 0和偏移,否则 transition 不触发 - JS 触发时,给每个
<li>依次加show类,延迟可用setTimeout或CSS @property(较新) - 别用
transition-delay直接写死在 CSS 里——那样所有项会同时开始延迟,而非逐个延迟
用 height + overflow 模拟展开收起
适合手风琴式列表、折叠面板里的子项。注意:height 不能从 auto 过渡,必须用具体数值或 max-height 替代。
错误写法:height: auto → height: 40px(不生效)
可行写法:
.accordion-item {
overflow: hidden;
max-height: 0;
transition: max-height 0.3s ease, opacity 0.3s ease;
}
<p>.accordion-item.open {
max-height: 200px; /<em> 需预估足够大的值 </em>/
opacity: 1;
}-
max-height要大于内容实际高度,否则会截断;太大会导致动画变慢(因要过渡到一个远超需要的值) - 配合
opacity可缓解“突然弹出”的生硬感 - 如果列表项高度差异大,建议 JS 动态读取
scrollHeight后再设max-height,否则纯 CSS 方案难兼顾准确与流畅
JS 控制时机比 CSS 更关键
很多效果失败,不是 CSS 写错了,而是类名添加时机不对。比如:
- 在 DOM 渲染前就加了
show类 → 动画根本不会播放 - 用
innerHTML批量插入<li>后立刻加类 → 浏览器可能还没完成 layout,transition 丢帧 - 想实现“添加新项时淡入”,但新
<li>插入后没触发 reflow → 需要offsetHeight强制触发或用requestAnimationFrame
推荐安全写法:
const newItem = document.createElement('li');
newItem.textContent = 'New item';
list.appendChild(newItem);
<p>// 强制重排,确保初始状态被读取
newItem.offsetHeight;</p><p>// 再触发动画
newItem.classList.add('show');复杂交互中,CSS 动画只是表层,JS 对节点生命周期的把控才是决定是否“自然”的分水岭。


















