transition 必须写在初始 class 中,否则 opacity 动画失效;正确写法是 class="modal transition-opacity duration-300 opacity-0",错误是动态添加 transition 类;需配合 visibility-hidden 或 pointer-events-none 避免可访问性问题。

直接用 v-if 或 display: none 控制模态框显隐,transition 一定失效——因为 display 不可过渡,且 v-if 会跳过渲染阶段,根本没机会触发过渡。
transition-opacity 必须写在初始 class 里
浏览器只会在元素首次渲染时读取 transition 声明。如果等模态框打开时才动态加 transition-opacity 类,opacity 变化就是硬切。
- 正确写法:
class="modal transition-opacity duration-300 opacity-0"(初始状态就带 transition) - 错误写法:
class="modal"+ JS 后续加transition-opacity和opacity-100,动画不触发 - Tailwind 用户注意:
transition-opacity是独立工具类,不能靠duration-300自动附带
opacity-0 不等于隐藏,必须配 visibility 或 pointer-events
opacity: 0 的元素仍占布局空间、能响应点击和 tab 键聚焦,用户可能误操作或影响可访问性。
- 安全组合:同时设
opacity-0+visibility-hidden(或pointer-events-none) - 别混用
visibility: hidden和transition: visibility:visibility 本身不可平滑过渡,加了也白加,只会让动画提前卡死 - 若需保留占位(如 tooltip 淡出后 hover 仍生效),只禁用交互:
opacity-0 pointer-events-none
transitionend 事件必须过滤 propertyName
一个元素可能同时过渡多个属性(比如 opacity + transform),但你只关心 opacity 动画结束的时机来清理 DOM。
立即学习“前端免费学习笔记(深入)”;
- 监听时加判断:
if (e.propertyName === 'opacity') - 再检查当前值是否真为 0:
getComputedStyle(el).opacity === '0',避免因重排中断或 CSS 覆盖导致误判 - 别用
setTimeout替代:300ms 写死不保险,动画可能被系统节流或强制降帧 - Vue 用户慎用
<transition>默认行为:它默认用display: none卸载,会跳过 opacity 过渡;应改用v-show+ 手动 class 切换
最易忽略的一点:transition 规则必须写在“非交互态”的基础 class 里,比如 .modal,而不是 .modal.open 或 .modal:hover——否则回退动画(关闭时)根本不会执行。


















