animation-play-state 是唯一能动态暂停动画而不重置帧的css属性,取值为running或paused,需配合已声明的animation使用,支持css悬停和js控制,但不支持transition且移动端需用touch事件适配。

animation-play-state 为什么能暂停动画
animation-play-state 是 CSS 中唯一能动态控制动画运行/暂停的属性,取值只有 running 和 paused。它不重置动画帧,只是冻结当前播放位置——这点和 display: none 或 visibility: hidden 完全不同,后者会中断并重置动画状态。
关键在于:它必须作用在已声明 animation 的元素上,且只能影响该元素自身正在运行的动画(对 @keyframes 无直接作用)。
鼠标悬停暂停的写法与常见错误
最简写法是用 :hover 伪类切换状态:
div {
animation: slide 3s infinite;
}
div:hover {
animation-play-state: paused;
}
但实际中容易踩这些坑:
- 没写初始
animation声明,只靠 hover 添加——animation-play-state不会“启动”动画,它只控制已开始的动画 - 用了
animation: none或animation: unset在 hover 里——这会清空整个动画,不是暂停,而是终止+重置 - 多个动画同时存在时,只改其中一个的
animation-play-state没效果——必须确保选择器匹配到对应动画所在的元素层级 - 用
transition过渡animation-play-state——无效,该属性不支持过渡
配合 JavaScript 动态控制更灵活
纯 CSS 悬停暂停适合简单场景;如果需要点击切换、条件暂停或与其他逻辑联动,JS 更可靠:
给元素加 class 控制状态比内联 style 更易维护:
.paused { animation-play-state: paused !important; }
然后用 JS 切换:
const el = document.querySelector('.animated');
el.addEventListener('mouseenter', () => el.classList.add('paused'));
el.addEventListener('mouseleave', () => el.classList.remove('paused'));
注意点:
- 加
!important是为了覆盖 CSS 中可能存在的running声明(尤其当动画在媒体查询或更高优先级规则里定义时) - 不要用
el.style.animationPlayState = 'paused'—— 驼峰写法在 JS 中生效,但容易被后续 CSS 规则覆盖,class 方式更稳定 - 动画正在播放时添加
pausedclass 立即生效;但如果动画刚结束(animation-fill-mode: forwards下),暂停状态可能不可见,需检查animation-iteration-count
移动端 touch 事件怎么处理
移动端没有 :hover,单纯依赖 CSS 无法实现“悬停暂停”。必须用 JS 监听 touchstart / touchend:
el.addEventListener('touchstart', () => el.classList.add('paused'));
el.addEventListener('touchend', () => el.classList.remove('paused'));
但要注意:
- touchstart 后立刻暂停,用户手指还没抬起来,动画就停了——体验可能突兀,可考虑加短延时或结合
pointer-events: none避免误触 - iOS Safari 对
animation-play-state的支持从 iOS 13.4 开始才稳定,旧版本可能回退为跳帧或失效 - 避免在
touchmove中频繁 toggle class,容易触发卡顿
真正麻烦的不是怎么写,而是动画本身是否设计为可暂停——比如用 steps() 实现的逐帧动画,暂停后可能卡在非整帧位置,视觉上不自然。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











