transition不提供“保持终态”开关,其结束后“弹回去”是因为目标样式未真实持续生效;必须通过class切换、内联样式固化或transitionend事件配合getComputedStyle来确保终态值稳定存在。

transition 本身不提供“保持终态”的开关,它只负责过渡过程;要让元素停在结束位置,必须让目标样式值真实、持续地生效。
为什么 transition 结束后会“弹回去”
常见错误现象:hover 里写 transform: scale(1.2),鼠标移开就恢复原状;JS 加 class 触发动画,class 一删状态就丢。
根本原因不是 transition 失效,而是触发过渡的样式来源消失了——比如 :hover 状态退出、临时 class 被移除、内联样式被清空。浏览器没地方读取“最终值”,只能回退到该属性未声明时的默认计算值(通常是 none 或 0)。
- transition 不改变元素的最终计算样式,只插值变化过程
- 没有类似
animation-fill-mode: forwards的 CSS 属性来“锁定” transition 终态 - 所谓“保持”,本质是让目标值在 DOM 生命周期中稳定存在
用 class 切换固化终态(最推荐)
避免 JS 动态写 style,直接用 CSS 规则定义“结束态”,靠 class 存在与否控制状态持久性。
立即学习“前端免费学习笔记(深入)”;
- 基础类中声明
transition,但不写终态属性 - 单独定义一个
.active类,明确写出目标值,如transform: translateY(-25px) - JS 只做
el.classList.add('active')或.remove('active') - 不要把
transition和终态写在同一个 class 里,否则浏览器可能判定“无变化”,不触发过渡
示例:
.box {
transition: transform 0.3s ease;
}
.box--lifted {
transform: translateY(-25px);
}
这样,只要 .box--lifted 在 classList 里,位移就一直生效;移除它才恢复。
用 transitionend + getComputedStyle 动态固化
适合无法预设终态值的场景,比如 JS 计算出的动态 height、transform 矩阵等。
- 监听
transitionend,用event.propertyName过滤目标属性(避免多个属性触发多次) - 调用
getComputedStyle(el).transform获取当前渲染值(注意:返回的是 matrix 字符串) - 写入
el.style.transform—— 内联样式优先级高,能覆盖原有规则 - 多个属性需分别读取、分别写入,不能只读一个
注意:getComputedStyle 返回的 transform 是矩阵,若需可维护的字符串(如 translateY(-25px)),得自己解析或改用 transformOrigin + 偏移量缓存。
容易踩的坑和兼容性提醒
这些点实际项目里最容易漏掉:
-
transition-property: all看似省事,但对display、height: auto、font-weight: bold等不可插值属性完全无效,上线前务必显式列出可过渡属性 - 页面前进/后退时,bfcache 会冻结 DOM 状态,
transition不会重播;需配合pageshow事件 +sessionStorage恢复 class 并用setTimeout(, 0)强制重排再加类 - 用
margin-top做位移会触发重排,性能差;优先用transform: translateY(),它与 transition 兼容性一致且更高效 - 不要在
transitionend里直接操作 class,可能因异步时机导致样式被覆盖;固化终态优先走style写入,或确保 class 规则足够强
真正难的不是写对那几行 CSS,而是想清楚:这个“最终状态”到底由谁来负责维持——是 CSS 规则、JS 数据、还是用户交互生命周期?选错载体,后面全是补丁。


















