应优先使用 prefers-reduced-motion 媒体查询响应系统级动效偏好,配合移动端阴影轻量化(blur-radius 2–4px、透明度 0.06–0.08)、JS 同步监听与老旧 WebView 的 UA 兜底策略。

直接用 @media (max-width: 480px) 或 UA 判断低性能手机来精简阴影动画,效果差且不可靠。真正有效的方式是响应用户系统级偏好,再辅以轻量级兜底策略。
优先用 prefers-reduced-motion 做语义化降级
这是 WCAG 认证、全平台支持的标准方案,iOS 低电量模式、Android 辅助功能、Windows/macOS 可访问性设置都会触发它,比任何设备特征判断都贴近真实需求。
- 所有含
text-shadow或box-shadow的过渡/动画规则,必须包裹在@media (prefers-reduced-motion: reduce)中 - 内部统一设为:
transition: none; animation: none; text-shadow: none; box-shadow: none; - 别只清空动画,还要补终态:比如
opacity: 1 !important; transform: none !important;,防止元素卡在中间状态
移动端 box-shadow 要主动轻量化,不等媒体查询触发
iOS Safari 和旧版安卓 WebView 对阴影渲染限制多,发虚、裁剪、闪烁很常见,不能等到“动画被禁”才处理。
- 把
blur-radius控制在 2px~4px,避免写12px这类桌面惯用值 - 透明度调低:用
rgba(0,0,0,0.06)~0.08替代0.15,视觉更干净,GPU 压力更小 - 加
transform: translateZ(0)强制合成层,解决 iOS 阴影不显示问题;但要避开will-change: transform,老 WebKit 容易白屏
JS 层同步拦截,覆盖 CSS 管不到的场景
CSS 媒体查询对 JS 动画、骨架屏、滚动触发动画无效,必须手动监听并降级。
立即学习“前端免费学习笔记(深入)”;
- 初始化时读取:
const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)") - 监听变化:
motionQuery.addEventListener("change", () => document.documentElement.classList.toggle("reduced-motion", motionQuery.matches)) - 所有 JS 启动前加判断:
if (!motionQuery.matches) { startLoadingAnimation() } - 骨架屏、加载指示器等,直接设终态样式:
el.style.opacity = "1"; el.style.transform = "none"
老旧安卓 WebView 需要 JS 兜底识别
Safari 13+/Chrome 74+ 支持 prefers-reduced-motion,但 Android 4.4–6 的系统 WebView 完全不识别,得组合条件判断。
- 用 JS 检测:
matchMedia("(max-width: 480px) and (max-resolution: 1.5dppx)").matches && /WebView|Android 4/.test(navigator.userAgent) - 命中后给
<html>加 class:no-animation - CSS 中写:
.no-animation .card { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }



















