应默认尊重系统“减少运动”偏好,用prefers-reduced-motion媒体查询强制降级动画时长与迭代次数,并避免依赖transitionend事件;关键交互需解耦状态变更与视觉反馈,且优先质疑动画必要性。

过渡动画会触发用户的前庭敏感或视觉疲劳
对部分用户来说,CSS transition 和 animation 不只是“看起来更顺滑”,它们可能直接引发头晕、恶心或注意力涣散——尤其是涉及位移(transform: translate())、缩放(scale())或不规则旋转的动画。WCAG 2.2 明确将这类运动归为“可关闭、可暂停、可减少”的需求项。
用 prefers-reduced-motion 媒体查询主动降级动画
这不是“加个开关让用户自己关”,而是默认尊重系统级偏好。macOS、Windows 和 iOS 都提供“减少运动”全局开关,浏览器会通过 @media (prefers-reduced-motion) 暴露该状态。
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}注意:0s 在某些旧版 Safari 中会被忽略,用 0.01ms 更可靠;!important 是必要的,否则组件内联样式或高优先级 CSS 可能覆盖它。
避免在关键交互路径中依赖过渡完成状态
比如用 transitionend 事件来触发下一步 DOM 操作(如删除元素、切换表单步骤),一旦用户启用了“减少运动”,这个事件可能永不触发——因为过渡被强制跳过,transitionend 不会派发。
立即学习“前端免费学习笔记(深入)”;
- 改用
setTimeout+ 固定延时(需与 CSS 中的transition-duration同步维护) - 或改用
getComputedStyle(el).transitionDuration动态读取,再做延时 - 更稳妥的方式:把“状态变更”和“视觉反馈”解耦,用 class 切换控制状态,用 JS 控制是否启用过渡
“减少幅度”不等于“去掉动画”,而是控制变量范围
例如导航下划线从左到右滑动,原方案用 width: 0 → 100% + left: 0 → 100%,幅度大且含位移。可改为仅改变 width,并限制最大宽度为容器的 30%,同时将缓动函数换成更平缓的 cubic-bezier(0.33, 1, 0.68, 1)。
.nav-underline {
width: 0;
transition: width 0.3s cubic-bezier(0.33, 1, 0.68, 1);
}
@media (prefers-reduced-motion: reduce) {
.nav-underline {
transition: none;
}
}真正容易被忽略的是:过渡的“起始/结束值”本身是否必要。很多所谓“动效优化”,其实第一步该问——这个变化,非得动吗?










