该在小屏设备上禁用或降级动画。低端手机性能差,应优先用transform/opacity,禁用触发重排的属性;用prefers-reduced-motion响应系统设置比媒体查询更可靠;@keyframes不可在@media内重定义,需多套命名动画切换;JS动画需手动监听matchMedia并管理状态。

动画在不同屏幕尺寸下该不该播放
大多数情况下,小屏设备(尤其是低端手机)的动画性能较差,强行播放 transform 或 opacity 动画仍可能掉帧。媒体查询不是用来“换动画效果”,而是决定“是否启用动画”或“降级为简化版”。
- 桌面端保留完整时长、缓动和关键帧;移动端可设为
animation: none或改用transition替代循环动画 - 避免在
@media (max-width: 768px)中仅修改animation-duration——这无法解决重绘压力,反而让节奏更难控制 - 若必须保留动画,优先用
transform和opacity,禁用left/top/background-color等触发重排/重绘的属性
用 prefers-reduced-motion 比媒体查询更可靠
用户是否需要减少动画,取决于系统设置,而非屏幕尺寸。iOS/Android/macOS/Windows 都提供「减少运动」开关,CSS 可直接响应:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
注意:!important 是必要的,否则容易被组件内联样式或高权重选择器覆盖;0.01ms 比 0s 更稳妥——某些浏览器对 0s 仍有微弱渲染行为。
媒体查询中重定义动画关键帧会失效
CSS @keyframes 是全局作用域,不能在 @media 内重新声明同名动画——浏览器会忽略整个 @keyframes 块。正确做法是定义多套命名动画,再用媒体查询切换:
立即学习“前端免费学习笔记(深入)”;
@keyframes slideInDesktop {
from { transform: translateX(-20px); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes slideInMobile {
from { transform: translateY(10px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.card {
animation: slideInDesktop 0.4s ease-out;
}
@media (max-width: 768px) {
.card {
animation-name: slideInMobile;
animation-duration: 0.25s;
}
}
关键点:animation-name 必须显式重写,不能只改 animation-duration——否则仍运行原动画。
JS 驱动动画时如何响应媒体查询变化
纯 CSS 动画靠媒体查询自动切换,但用 requestAnimationFrame 或 gsap.to() 控制的动画不会自动响应。需监听 resize 或使用 matchMedia:
const mediaQuery = window.matchMedia('(max-width: 768px)');
function handleMediaChange(e) {
if (e.matches) {
// 移动端:停止当前动画,启动简化逻辑
gsap.killTweensOf('.hero');
gsap.set('.hero', { y: 10, autoAlpha: 0 });
} else {
// 桌面端:恢复完整动画
gsap.from('.hero', { y: -20, autoAlpha: 0, duration: 0.6 });
}
}
mediaQuery.addListener(handleMediaChange);
handleMediaChange(mediaQuery); // 初始化
注意:matchMedia 比 resize 事件更精准,不因滚动、缩放触发误判;但需手动管理动画销毁,否则容易叠加冲突。
复杂点在于:动画状态(如进行中、已完成)和媒体断点之间没有自动同步机制,必须由开发者显式维护。这点最容易被忽略。










