因为display不是可动画属性,浏览器不支持其过渡;真正可动画的只有opacity、transform、visibility三者组合。

为什么直接给 display 加 transition 没用
因为 display 不是可动画的 CSS 属性,浏览器根本不支持对它做过渡。你写 transition: display 0.3s,等于没写。更糟的是,如果弹窗初始是 display: none,后续加 display: block 再加动画类,第一帧常被跳过——浏览器把样式计算合并了,压根没“看到”初始态。
真正能动画的组合只有三个:opacity、transform、visibility。其中 visibility 控制是否参与渲染和交互,opacity 控制透明度,transform 控制位移/缩放。三者必须配合使用:
-
visibility: hidden时元素仍占布局空间,但不可点击、不可聚焦 -
opacity: 0+transform: scale(0.95)是安全的入场起始态,人眼感知为“未出现” - 动画结束前不能改
visibility: hidden,否则关闭按钮点不到(尤其移动端 touch 事件失效)
<dialog></dialog> 的 showModal() 为什么动不了
因为 showModal() 内部会立即设 display: block 并同步阻塞交互,CSS 过渡根本来不及启动。这不是 bug,是规范行为。想加动画,必须绕开它:
- 不用
showModal(),改用dialog.show()(非模态),自己画 backdrop 和 trap focus - 给
<dialog></dialog>加open属性后,立刻用 JS 添加入场类(如is-opening) - 添加类后,**必须**执行
dialog.offsetWidth强制触发重排,让浏览器“记住”初始opacity和transform值 -
dialog::backdrop也要单独加transition: opacity 0.3s,否则遮罩层闪一下才淡入
移动端弹窗缩放动画卡顿怎么办
纯靠 transform: scale() 在 iOS Safari 或低端安卓机上容易掉帧,尤其配合背景模糊时。关键不是写法错,是没启用 GPU 加速:
- 给弹窗容器加
will-change: transform, opacity,告诉浏览器这个元素要动 - 确保
transform值含translateZ(0)或translate3d(0, 0, 0),强制走合成层 - 避免在动画中读取
offsetTop、getBoundingClientRect()等触发布局的操作 - Safari 对
dialog::backdrop的transition支持不全,建议 fallback 到background-color: rgba(0,0,0,0.5)+-webkit-backdrop-filter: blur(2px)
退出动画结束后怎么安全清理状态
很多人在加完 is-closing 类后直接调用 dialog.close(),结果动画只播了一半就消失了。正确顺序是:
- 先加
is-closing类(含opacity: 0+transform: scale(0.9)) - 再执行
dialog.offsetWidth触发重排 - 监听
transitionend事件,且只响应一次(加{ once: true }) - 在回调里调用
dialog.close(),并移除is-open类(不是is-closing) - 如果用
setTimeout替代事件监听,时间必须 ≥ CSS 中写的 transition 时长,且要加 50ms 容差
漏掉 once: true 或提前移除类名,会导致连续点击关闭按钮时动画错乱或焦点丢失——这是最常被忽略的细节。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











