旧浏览器不支持(prefers-reduced-motion: reduce),需用JS分层检测+class控制降级,CSS与JS解耦,SSR环境延迟执行并内联JS避免闪动。
IE、Edge ≤16、Safari ≤13.1、Firefox ≤63 这些浏览器压根不认识 prefers-reduced-motion 媒体查询,整条 @media 规则会被直接忽略——不是失效,是语法错误,DevTools 里整块样式灰掉,连 fallback 都不会触发。
这意味着:你写的降级规则在这些环境里完全不存在,动画照常运行,无障碍意图彻底落空。
@supports (prefers-reduced-motion: reduce) 检测支持性——@supports 对媒体特性支持极差,且旧浏览器连这个语法都不认旧浏览器虽不支持 CSS 媒体查询,但部分(如 IE10+、Edge 12+)能执行 window.matchMedia,只是返回 .matches === false(即使系统已开启)。更老的版本(IE9 及以下)则根本没这个 API。
实操上要分三层覆盖:
window.matchMedia 是否存在且可调用;若否,直接走「保守降级」路径(如默认禁用所有动画类)window.matchMedia("(prefers-reduced-motion: reduce)").matches 获取初始值——注意:iOS Safari 13 及更早版本可能返回 false 即使系统已开启,所以不能只信首次结果addEventListener("change") 的旧环境(如 IE),改用定时轮询 matchMedia().matches(间隔 500ms),或干脆放弃监听,仅做初始化判断把旧浏览器适配逻辑和现代 CSS @media 完全解耦,否则容易互相覆盖或产生竞态。关键原则是「CSS 管视觉降级,JS 管行为拦截」。
@media (prefers-reduced-motion: reduce) { ... },专注处理 transition 和 animation 时长压缩<html> 加 data-reduced-motion="true",再用属性选择器写降级样式:html[data-reduced-motion="true"] .card { animation-duration: 0.01ms !important; }
if (!reducedMotionEnabled()) { animateIn(el); },而不是依赖 CSS 类自动生效旧浏览器往往也跑在 SSR(服务端渲染)环境里,而 Node.js 无 matchMedia,服务端永远拿不到真实用户偏好。如果只靠客户端 JS 注入 class,首屏会闪动(先渲染带动画的 DOM,再降级)。
解决方式很实际:
DOMContentLoaded 后执行<head> 中内联一段极简 JS,立即读取 matchMedia 并同步加 class 到 <html>,避免 FOUC@media print, (prefers-reduced-motion: reduce) { ... } ——旧浏览器虽不认后者,但至少 @media print 能生效,确保打印时动画静默真正麻烦的不是写不出兼容代码,而是得同时追踪三套状态:系统偏好、CSS 媒体查询是否就绪、JS 检测是否完成。漏掉任意一环,降级就变成随机生效。