正确写法是@media (prefers-reduced-motion: "reduce"),必须严格匹配大小写与英文双引号;仅设animation: none会破坏交互,须同步重置transition-duration、scroll-behavior,并手动降级JS动画。

如何正确书写 @media (prefers-reduced-motion: reduce) 媒体查询
必须写成带引号的完整关键字值,不能简写或布尔化。常见错误是写成 @media (prefers-reduced-motion: true) 或漏掉引号、空格,这会导致整个规则失效。正确的只有两种形式:@media (prefers-reduced-motion: reduce) 和 @media (prefers-reduced-motion: no-preference)。前者匹配用户主动开启系统“减少动画”设置(macOS 的「减少动态效果」、Windows 的「显示动画」关闭、Android/iOS 的「降低动态效果」等),后者仅在用户未做任何选择时生效——但别依赖它做默认动画逻辑,因为多数浏览器默认就是 no-preference,无需显式声明。
哪些 CSS 动画/过渡必须覆盖
只禁用 animation 不够,transition 同样会触发眩晕感。二者需同时归零:
-
animation: none或animation-duration: 0.01s(保留类名结构但视觉无感) -
transition: none或transition-duration: 0.01s - 特别注意
scroll-behavior: smooth,它属于独立属性,需单独在媒体查询中设为scroll-behavior: auto - 慎用
opacity: 0类动画——哪怕时间极短,也可能被识别为闪烁;改用visibility: hidden; height: 0更稳妥
为什么 JS 动画不会自动响应这个媒体查询
CSS 媒体查询对 requestAnimationFrame、GSAP、Lottie、Canvas 渲染或轮播组件的自动播放完全无效。系统偏好变更后,这些 JS 动画照常运行,CSS 层面的降级形同虚设。
- 必须手动初始化监听:
const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)") - 启动前判断,而非运行中暂停:
if (!motionQuery.matches) { startParallax() } - 监听变化(Safari 14+ 支持
change事件):motionQuery.addEventListener("change", handleMotionChange) - 旧版 Safari 需首次加载后立即执行一次
handleMotionChange,否则可能错过初始状态
骨架屏、loading spinner 等场景的终态处理
这类元素往往依赖 CSS 动画循环渲染,但用户开启“减少动画”后,不能让它卡在中间帧或残留 transform/opacity 状态。
立即学习“前端免费学习笔记(深入)”;
- 直接设终态样式,跳过动画过程:
el.style.opacity = "1"; el.style.transform = "none"; - 避免使用
display: none立即隐藏——可能造成布局抖动或内容闪现;优先用visibility: hidden+ 尺寸归零 - 若用伪元素实现 spinner,应在媒体查询内直接移除
animation并重置::after的transform和opacity
@media (prefers-reduced-motion: reduce),却忘了轮播图仍在自动滚动、视差仍在计算位移——那套 CSS 规则只是给浏览器看的,JS 才真正控制着页面的“运动权”。


















