transition 无法作用于 display 属性,因其为离散枚举值,无中间状态;正确做法是用 opacity 与 visibility 组合,并配合 JS 强制重排确保动画触发。

display 是离散属性,浏览器压根不计算中间值
你写的 transition: display 0.3s 不是写错了,而是被浏览器静默丢弃——DevTools 的 Computed 面板里根本找不到这条规则。因为 display 只能取 none、block、flex 等枚举值,没有“半显示”这种中间状态。一旦设成 display: none,元素立刻从渲染树中移除,所有后续动画逻辑直接终止。
transition 失效的常见误操作场景
以下情况看似合理,实则都会导致过渡跳变:
- 在
:hover或临时 class 中写transition:一旦 class 被移除,transition 声明消失,浏览器失去过渡上下文 - JS 中连续执行
el.style.display = 'block'和el.classList.add('fade-in'):浏览器合并渲染,跳过起始帧 - 依赖
height: auto做过渡:auto 不是数值,无法插值;transition: height 0.3s在 auto → 具体值时必然失效 - 用
transition: all 0.3s试图“一劳永逸”:遇到display、z-index等不可插值属性,整条声明不会报错,但对应属性无效果
opacity + visibility 组合必须显式协同控制
这不是简单替换两个属性,而是分工明确的配合:
-
opacity控制视觉渐变(0 → 1),必须出现在transition列表中 -
visibility控制交互与占位(hidden↔visible),也必须显式声明进transition,否则会瞬切 - 初始态必须同时设
opacity: 0和visibility: hidden,只靠opacity: 0仍挡点击、抢焦点 - 推荐写法:
.el { opacity: 0; visibility: hidden; transition: opacity 0.25s ease, visibility 0s 0.25s; }——其中visibility 0s 0.25s表示延迟生效,卡在opacity动画结束那一刻
JS 触发时必须打断渲染队列
光写对 CSS 不够,JS 操作顺序决定动画是否真正启动:
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
el.style.display = 'block'; el.classList.add('fade-in');→ 合并为一次渲染,无起始帧 - 正确写法:先设
el.style.display = 'block',再读一个强制重排的属性(如el.offsetHeight),最后加 class - 别用
getComputedStyle代替offsetHeight:前者不一定触发重排,后者才强制 layout - 高频调用(如滚动中反复显示)慎用该技巧,易引发 layout thrashing 导致卡顿
真正难的不是让 opacity 动起来,而是判断要不要释放 DOM 占位空间、键盘焦点如何接管、父容器 overflow: hidden 下是否需 JS 补位——这些决策点,往往比 CSS 规则本身更影响最终体验。


















