尊重「减少动态效果」偏好
大幅度的旋转、视差、飞入对部分用户会引起眩晕 / 不适。系统层面有「减少动态效果」开关,CSS 用
@media (prefers-reduced-motion: reduce) 读它——命中时应当关掉或换成更轻的动画(把「大幅位移」降级为「淡入」),而不是全部删除、让界面失去状态反馈。这是动画的基本无障碍要求。
1 · 媒体查询
prefers-reduced-motion 有两个取值:
| 值 | 含义 |
|---|---|
no-preference |
用户没有要求减少动效(默认) |
reduce |
用户在系统里开启了「减少动态效果」 |
JS 侧用 matchMedia('(prefers-reduced-motion: reduce)').matches 读当前值,并可 addEventListener('change', …) 在用户切换系统设置时实时响应。
/* 粗粒度做法: reduce 时把所有动画 / 过渡压到几乎瞬时 */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
transition-duration: .01ms !important;
scroll-behavior: auto !important;
}
}
/* 更好: 针对性地把「大动作」换成「轻动作」, 而不是大幅飞入 */
@media (prefers-reduced-motion: reduce) {
.hero { animation: fade-in .4s ease both; }
}
2 · 对比 reduce 前后
无法在页面里改你的系统设置,所以下面给一个模拟开关:打开后,舞台会套用与 @media (prefers-reduced-motion: reduce) 等效的规则——方块从「旋转」降级为「淡入淡出」。旁边同时显示你真实的系统偏好(由
matchMedia 实时读取);另有一个暂停按钮,把「是否播放」的控制权交给用户。
实践建议: 默认给动效,在 reduce 里降级——优先保留必要的状态反馈(展开 / 选中 / 加载),去掉的是装饰性大动作(视差、自动轮播、大幅缩放位移)。把「是否播放动效」的控制权交给用户,是同一条无障碍原则的延伸。