动画执行完弹回原样是因浏览器默认不保留终态,需用 animation-fill-mode: forwards 锁定终帧;transition 替代时须明确定义基础样式;JS 操作优先用 class 切换而非清空内联 style;弹窗场景需防 iOS 回弹干扰。

动画执行完立刻“啪”一下弹回原样,不是动画写错了,是浏览器默认不保留终态。关键在控制动画结束后的样式停留逻辑。
用 animation-fill-mode: forwards 锁定终帧
这是最直接有效的解法。CSS 动画默认只在播放期间生效,一停就退回到初始状态,forwards 就是告诉浏览器:“停在最后一帧,别动”。
- 必须加在触发动画的选择器里,比如
.btn:hover { animation: scaleIn 0.3s forwards; } - 不能只写
animation: scaleIn 0.3s—— 缺少forwards就等于没锁住 - 如果动画本身含多个关键帧(如
@keyframes中定义了 0%、50%、100%),终态以 100% 的样式为准
用 transition 替代 animation 时,基础样式必须明确定义
过渡动画依赖“起始值 → 终止值”的计算,若基础样式里没声明对应属性,浏览器可能 fallback 到 auto 或 none,导致跳变或抖动。
- 例如 hover 缩放:基础样式要写
.btn { transform: scale(1); },hover 里写transform: scale(1.08); - 改颜色?基础样式就得有
background-color: #333;,hover 里才写新色值 - 避免只在 hover 里设
background-position却漏掉background-size和background-repeat,这些不参与过渡的属性会引发错位
慎用内联 style 移除操作,优先交由 class 控制
JS 手动清除 style 属性(如 el.style.transform = '')会强制覆盖所有内联 transform,哪怕它原本是其他逻辑设置的,极易引发意外回弹。
- 推荐用 class 切换:添加
.is-animated触发动画,移除该 class 即可退场 - 若必须用 JS 控制,用
el.style.removeProperty('transform')比赋空字符串更安全 - 移除前检查是否还有其他 JS 正在写该属性(比如滚动监听、视差逻辑),避免冲突
弹窗/浮层类场景:防止遮罩层外区域触发回弹干扰
当动画发生在弹窗内,而用户手指在遮罩层上滑动,iOS 可能误触发页面级回弹,造成视觉“撕裂”感,看起来像动画被拉扯回退。
- 弹窗显示时,给
body加临时 class(如no-scroll),配合 CSS:body.no-scroll { overscroll-behavior: none; } - 同时对遮罩层绑定精准
touchmove拦截:{ passive: false }+e.preventDefault(),但仅限遮罩区域 - 关闭弹窗后及时移除 class 和事件监听,避免影响后续滚动


















