必须用@media (prefers-reduced-motion: reduce)检测,因该媒体查询仅支持reduce和no-preference两个标准值,写true、漏引号、大小写错误均导致规则被忽略;transition和animation须声明在基础选择器中,否则移出时跳变,且需重置transform、opacity等属性并监听js动画。

必须用 @media (prefers-reduced-motion: reduce) 检测,写成 true、漏引号、大小写错误(如 Reduce)都会让整条规则被浏览器忽略——DevTools 里媒体查询块变灰,就是它没生效的明确信号。
为什么 @media (prefers-reduced-motion: true) 完全不工作
这个媒体查询只接受两个标准化值:reduce 和 no-preference,没有布尔类型。写成 true、1 或不加引号的 reduce 都是语法错误。macOS、Windows 10+、iOS 开启“减少动态效果”后触发的始终是 reduce,它是个用户意图信号,不是 JS 变量。
真机测试时 iOS Safari 对语法更严格:reduce 必须带英文双引号且全小写,即 "reduce" —— 虽然多数浏览器宽容,但 Safari 16.4+ 会直接跳过非法声明。
哪些地方容易漏掉声明,导致动画“部分失效”
常见错误是只在状态类里写动画,比如:
button:hover { transition: transform 0.2s; }
这样移出时无过渡声明,浏览器无法插值,结果就是硬切跳变——@media 根本没机会介入。
- 必须把
transition和animation写在基础选择器中,例如button { transition: transform 0.2s; } - 第三方组件(如
.ant-collapse-content-active)若只在展开态定义transition,也要补上默认态声明 - 内联样式(
style="animation: spin 1s")无法被媒体查询覆盖,需用 JS 动态控制或提前移除
除了 animation 和 transition,还要重置哪些属性
仅设 animation: none 和 transition: none 不够。只要参与视觉运动,以下属性在 reduce 模式下也得强制归零或压缩:
-
transform:最常用也最容易被忽略,必须加transform: none !important -
opacity:快速切换仍可能诱发眩晕;若需保留反馈,改用transition: opacity 0.1s linear而非完全关闭 -
max-height:折叠菜单依赖它过渡,建议保留transition: max-height 0.1s linear,避免内容截断 -
scroll-behavior:禁用平滑滚动,加html { scroll-behavior: auto !important; }
JS 动画怎么同步响应,而不是“假装降级”
CSS 媒体查询管不到 requestAnimationFrame、GSAP、Canvas 或轮播组件的自动播放。必须手动监听并降级:
- 初始化时获取状态:
const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)") - 监听变化(Safari 14+ 支持):
motionQuery.addEventListener("change", handleMotionChange) - 动画启动前判断:
if (!motionQuery.matches) { startAnimation() } - 不要轮询
matchMedia,也不要只在页面加载时检查一次——系统设置可能中途变更
最易被忽略的是:很多轮播库、图表动画、粒子背景都完全忽略这个信号,靠 CSS 媒体查询覆盖不了它们,必须进源码或封装层加判断逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











