transition结束后样式回退是因触发样式的来源消失,而非transition本身问题;应通过class切换、animation-fill-mode:forwards或transitionend+getComputedStyle固化终态。

transition 结束后元素样式自动回退?
默认情况下,transition 只控制「变化过程」,不改变元素的最终计算样式。如果触发过渡的 CSS 属性(比如 transform 或 opacity)在动画结束后被重置为初始值(例如通过 class 移除、伪类失效或 JS 清除内联样式),浏览器就会立刻跳回原状态——看起来就像“没保持住”。这不是 transition 本身的问题,而是样式来源消失了。
用 transitionend 事件 + getComputedStyle 固定最终值
适用于需要动态计算并锁定过渡终点的场景,比如 JS 控制的展开/收起动画后要维持高度,或 transform 动画后需固化位置。关键不是“复制当前值”,而是确保目标样式持续生效。
- 监听
transitionend事件,但注意:它可能被多次触发(每个过渡属性一次),建议用event.propertyName过滤 - 用
getComputedStyle(element).property获取过渡结束时的真实值(如getComputedStyle(el).transform) - 将该值写入
style属性(内联样式优先级高,可覆盖原有规则),例如:el.style.transform = computedTransform - 若涉及多个属性(如
transform和opacity),需分别读取并写入
更简单可靠的方式:用 class 切换代替临时样式
避免依赖 JS 读写样式,直接让 CSS 规则定义“结束态”。这是最常用也最稳定的方案。
- 不要用
el.style.transition = '...'; el.style.transform = '...';启动动画,而应预先定义好两个 class:
.box {
transition: transform 0.3s, opacity 0.3s;
}
.box--active {
transform: translateX(100px);
opacity: 0.8;
}
- JS 只负责切换:
el.classList.add('box--active')→ 过渡开始;过渡结束后,class 仍在,样式自然保持 - 若需“反向保持”,就保留目标 class;若需“恢复”,再
remove即可 - 注意:不要在同一个 class 里同时写
transition和终态属性,否则过渡可能不触发(浏览器认为无变化)
animation + animation-fill-mode: forwards 的替代思路
当 transition 不够用(比如需要多段关键帧、延迟、循环控制),改用 @keyframes 配合 forwards 更直观。
立即学习“前端免费学习笔记(深入)”;
-
animation-fill-mode: forwards会让元素在动画结束后**保持最后一帧的样式**,且优先级高于普通 class 规则 - 必须显式设置
animation(含 duration、timing-function、fill-mode),仅靠 keyframes 不会生效 - 与 transition 不同,animation 是声明式的,无需 JS 干预即可固化结果
@keyframes slideIn {
from { transform: translateX(-20px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.animated {
animation: slideIn 0.4s ease-out forwards;
}
过渡真正难的不是“怎么动”,而是动完之后谁来管状态归属——CSS 规则、JS 写入、还是动画模型,选错一层,后面所有交互逻辑都会被动摇。










