不能。transitionend仅触发已完成且有实际变化的transition,无变化、样式未生效、元素未渲染或属性不可过渡时均不触发,且不支持监听中断。

transitionend 事件能监听所有 transition 吗?
不能。transitionend 只触发已完成的、有实际变化的 transition。比如元素初始 opacity: 1,你又设成 opacity: 1,即使加了 transition: opacity 0.3s,也不会触发 transitionend——因为没有发生过渡。
常见误判场景:
- 元素刚插入 DOM 就立刻设置过渡属性(浏览器可能合并样式计算,跳过 transition)
- 使用了
transition: all 0.3s,但只改了未声明为可过渡的属性(如display、height在 auto 状态下) - 多个属性同时过渡,但只监听一次事件,却误以为覆盖全部
建议始终显式指定监听的属性名:event.propertyName === 'transform',避免被其他无关 transition 干扰。
为什么有时 transitionend 不触发?检查这三点
-
transition 样式必须在触发前已生效(不能 JS 设置 class 后立刻 el.style.transition = '...',需确保样式已由浏览器计算)
- 元素不能处于
display: none 或未渲染状态(offsetHeight 为 0 时 transition 不启动)
- 避免在 transition 过程中反复修改同一属性(如连续 10ms 改 5 次
left),会导致前序 transition 被中断,transitionend 不触发
transition 样式必须在触发前已生效(不能 JS 设置 class 后立刻 el.style.transition = '...',需确保样式已由浏览器计算)display: none 或未渲染状态(offsetHeight 为 0 时 transition 不启动)left),会导致前序 transition 被中断,transitionend 不触发简单验证法:
el.addEventListener('transitionend', e => console.log(e.propertyName, e.elapsedTime)),看控制台是否输出;没输出就回头检查 CSS 是否真正应用、属性是否真的变化。用 getComputedStyle 判断 transition 是否已开始?
不推荐主动轮询。但当你要「确保 transition 已进入执行阶段再做后续逻辑」时,可以这样兜底:
- 监听
transitionend,同时设一个略长于 transition-duration 的setTimeout(比如 350ms 对应 300ms 动画) - 在
transitionend回调里用clearTimeout清除定时器 - 定时器到期仍未触发事件,说明 transition 异常(被跳过、被覆盖或属性未变)
原因:CSS transition 的启动依赖浏览器样式布局阶段,JS 执行太快时容易「错过」这个时机,单纯靠事件监听不够鲁棒。
transitionend 在不同浏览器里的兼容细节
- Safari 旧版(≤13.1)对
transform 和 opacity 的 transitionend 触发更严格,若父元素有 will-change: transform,有时会抑制子元素事件
- Firefox 对
height: auto → 100px 这类过渡不触发 transitionend(因为 auto 无法插值)
- 所有浏览器都不支持监听
transition 的「取消」或「中断」,只有完成才发事件
transform 和 opacity 的 transitionend 触发更严格,若父元素有 will-change: transform,有时会抑制子元素事件height: auto → 100px 这类过渡不触发 transitionend(因为 auto 无法插值)transition 的「取消」或「中断」,只有完成才发事件如果你要处理动画中断场景(比如用户快速切换 tab 导致页面 visibilitychange),得结合 document.hidden + 手动清理状态,不能依赖 transitionend。
transitionend 本身很轻量,但它的触发时机高度依赖样式计算和渲染管线,写的时候别把它当成 JS 函数调用那样确定——它更像一个“尽力通知”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











