display 属性不支持 transition,因其为离散值且无中间状态;应改用 opacity + visibility 协同控制,配合 transition-delay 和 transitionend 事件精准管理动画时机与 dom 状态。

transition 在 display: none 下失效,不是写错了,是浏览器根本不会处理它——你写的 transition: display 0.3s 会被静默丢弃,DevTools 的 computed 面板里都找不到这条规则。
为什么 display 切换完全不触发 transition
display 是离散属性,取值只有 none、block、flex 等枚举值,没有中间状态。浏览器动画引擎无法插值计算“半显示”这种值,所以直接跳过 transition 流程。一旦设成 display: none,元素立刻从渲染树中移除,后续所有动画(包括你同时写的 opacity)都会被强制中止。
用 opacity + visibility 替代的实操写法
这不是简单换两个属性,而是分工明确、时机对齐的协同控制:
-
opacity负责视觉渐变(0 → 1),必须显式写进transition -
visibility负责交互与占位控制(hidden ↔ visible),也必须显式声明,否则会瞬切 - 初始态必须同时设
opacity: 0和visibility: hidden;只靠opacity隐藏会导致元素仍挡点击、抢焦点 - 推荐写法:
.el { opacity: 0; visibility: hidden; transition: opacity 0.25s ease, visibility 0s 0.25s; },其中visibility 0s 0.25s表示延迟生效,卡在opacity动画结束那一刻
快速开关时容易踩的坑
看似只是加个 visibility,但真实项目里翻车最多:
- 连续开关出现“闪一下又消失”:因为
visibility: hidden提前应用。解决方法是监听transitionend并过滤event.propertyName === 'opacity',或临时加pointer-events: none - 动画结束后没释放布局空间:若需像
display: none那样真正卸载,得在transitionend回调里补上el.style.display = 'none'和el.setAttribute('aria-hidden', 'true') - 父容器有
overflow: hidden且子元素占位,会导致滚动条抖动:此时仅靠visibility不够,必须 JS 清理 -
step-end很关键:它让visibility严格卡在最后一帧切换,避免opacity还没到1就突然可点;但别滥用——它会让切换显得生硬,适合模态框类控件
真正难的不是写出过渡,而是判断要不要保留占位、是否需要释放 DOM 空间、键盘焦点如何管——这些决策点,往往比 CSS 规则本身更影响最终体验。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











