低电量模式会强制启用 prefers-reduced-motion: reduce,导致 Safari 跳过所有 CSS 动画渲染,包括 @keyframes、transition 和 will-change 硬件加速效果,此为系统级硬性限制,无法通过前端绕过。

低电量模式会强制启用系统级的 prefers-reduced-motion: reduce 媒体查询,Safari 由此直接跳过所有 CSS 动画渲染流程,包括 @keyframes、transition 和 will-change 触发的硬件加速效果,这不是 Bug,而是 iOS/iPadOS 的硬性限制,无法通过前端代码绕过。
确认是否为低电量模式导致动画失效
别靠猜测判断,必须用 Safari DevTools 实时验证:在 Safari 中打开目标网页 → 按 Command+Shift+P(Mac)或 Ctrl+Shift+P(Windows/Linux)→ 输入 “reduced” → 选择 “Emulate CSS prefers-reduced-motion” → 切换为 reduce → 刷新页面。如果动画立刻消失,且 window.matchMedia('(prefers-reduced-motion: reduce)').matches 返回 true,就坐实了根源。
这一步操作起来很简单,直接调出命令面板搜关键词就行。
为什么只加 animation: none 不够
很多人只在媒体查询里写 animation: none,却忽略了 transition 和 will-change 在 reduce 模式下仍参与样式计算,造成严重副作用:
① transition: all 0.3s 这类声明即使不执行动画,也会阻塞 transitionend 事件触发,导致 JS 逻辑卡死;必须显式写成 【transition: none】,不能留空、不能注释掉、也不能写成 transition: none 0s。
② 纯装饰性动画(如旋转 loading 图标)若未补终态样式,降级后元素可能卡在中间角度——例如原 animation: spin 2s infinite 必须配 transform: rotate(0)。
③ 【will-change: transform】 在 reduce 下不仅无效,还可能引发图层错位或闪烁,建议一并移除。
JS 动效组件必须动态响应开关变化
不能只在页面初始化时检查一次 matchMedia 结果,因为用户可能在浏览中开启或关闭低电量模式。
方法一:使用现代 API 监听变化
const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
motionQuery.addEventListener('change', handler);
方法二:兼容旧版 Safari(
motionQuery.addListener(handler);
推荐统一给 添加 reduced-motion class,CSS 层接管视觉开关,JS 只负责切换 class,避免逻辑散落。


















