GPU-Accelerated Properties
Only these properties animate on the compositor thread (60fps):
| Property | Use |
|---|
| INLINECODE0 | Move, rotate, scale (translateX, rotate, scale) |
| INLINECODE1 |
Fade in/out |
Everything else triggers layout or paint. Avoid animating:
- -
width, height, margin, padding (layout thrashing) - INLINECODE6 ,
left, right, bottom (use transform instead) - INLINECODE10 ,
font-size (expensive reflows)
CODEBLOCK0
Reduced Motion
~5% of users experience vestibular disorders (dizziness, nausea from motion).
CODEBLOCK1
Keep subtle fades and color changes even with reduced motion. Remove parallax, bouncing, infinite loops.
Timing Functions
| Easing | Use case |
|---|
| INLINECODE12 | Elements entering view (appears responsive) |
| INLINECODE13 |
Elements exiting view (accelerates away) |
|
ease-in-out | Elements moving within view |
|
linear | Only for spinners, progress bars, color cycling |
CODEBLOCK2
Duration Guidelines
| Type | Duration |
|---|
| Micro-interactions (hover, focus) | 100-200ms |
| Transitions (modals, dropdowns) |
200-300ms |
| Page transitions | 300-500ms |
| Complex choreography | 500-1000ms max |
Anything over 500ms feels sluggish. Shorter is usually better.
CSS Transitions vs Animations
Transitions: A to B state changes
CODEBLOCK3
Animations: Multi-step, auto-play, looping
CODEBLOCK4
Use transitions for hover/focus states. Use animations for on-load effects and sequences.
will-change
Only use as optimization when you have specific performance problems:
CODEBLOCK5
Transition Property Specificity
CODEBLOCK6
INLINECODE16 can cause unexpected animations on color, background, border changes.
React/Framework Traps
Exit animations require AnimatePresence:
CODEBLOCK7
Stable keys for list animations:
CODEBLOCK8
AutoAnimate parent must be unconditional:
CODEBLOCK9
Library Selection
| Library | Size | Best for |
|---|
| CSS only | 0kb | Hover states, simple transitions |
| AutoAnimate |
3kb | Lists, accordions, toasts (90% of UI animations) |
| Motion | 22kb | Gestures, physics, scroll animations, complex choreography |
| GSAP | 60kb | Timelines, creative animation, scroll-triggered sequences |
Start with CSS. Add AutoAnimate for list animations. Only add Motion/GSAP for complex needs.
Common Mistakes
- - Animating
width/height instead of scale—causes layout thrashing - Infinite animations without pause control—no way to stop
- Same easing for enter and exit—use ease-out for enter, ease-in for exit
- Ignoring prefers-reduced-motion—causes physical discomfort
- Duration over 500ms—feels sluggish
- INLINECODE20 catching unintended properties
- Missing AnimatePresence for exit animations in React
GPU加速属性
只有这些属性可以在合成线程上实现动画(60fps):
| 属性 | 用途 |
|---|
| transform | 移动、旋转、缩放(translateX、rotate、scale) |
| opacity |
淡入/淡出 |
其他所有属性都会触发布局或绘制。避免对以下属性进行动画:
- - width、height、margin、padding(导致布局抖动)
- top、left、right、bottom(改用transform)
- border-width、font-size(昂贵的重排)
css
/ ❌ 每帧触发布局 /
.slide { left: 100px; transition: left 0.3s; }
/ ✅ GPU加速 /
.slide { transform: translateX(100px); transition: transform 0.3s; }
减少动画
约5%的用户患有前庭障碍(因运动导致的头晕、恶心)。
css
/ 仅在用户未请求减少动画时执行动画 /
@media (prefers-reduced-motion: no-preference) {
.animated { animation: slide-in 0.5s ease-out; }
}
/ 或者为请求减少动画的用户禁用 /
@media (prefers-reduced-motion: reduce) {
, ::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
即使在减少动画的情况下,也要保留微妙的淡入淡出和颜色变化。移除视差、弹跳、无限循环。
缓动函数
| 缓动类型 | 使用场景 |
|---|
| ease-out | 元素进入视图(显得响应迅速) |
| ease-in |
元素离开视图(加速离开) |
| ease-in-out | 元素在视图内移动 |
| linear | 仅用于加载旋转器、进度条、颜色循环 |
css
/ 自定义弹跳 /
transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
/ Material Design标准 /
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
持续时间指南
| 类型 | 持续时间 |
|---|
| 微交互(悬停、聚焦) | 100-200ms |
| 过渡(模态框、下拉菜单) |
200-300ms |
| 页面过渡 | 300-500ms |
| 复杂编排动画 | 最大500-1000ms |
超过500ms会感觉迟钝。通常越短越好。
CSS过渡 vs 动画
过渡: A到B的状态变化
css
.button { transform: scale(1); transition: transform 0.2s ease-out; }
.button:hover { transform: scale(1.05); }
动画: 多步骤、自动播放、循环
css
@keyframes fadeSlideIn {
0% { opacity: 0; transform: translateY(20px); }
100% { opacity: 1; transform: translateY(0); }
}
.card { animation: fadeSlideIn 0.5s ease-out forwards; }
悬停/聚焦状态使用过渡。加载效果和序列使用动画。
will-change
仅在遇到特定性能问题时作为优化手段使用:
css
/ ✅ 动画开始前应用,结束后移除 /
.card:hover { will-change: transform; }
.card { will-change: auto; }
/ ❌ 切勿全局应用 /
- { will-change: transform, opacity; } / 浪费GPU内存 */
过渡属性特异性
css
/ ❌ 动画化所有属性,包括非预期的属性 /
.card { transition: all 0.3s; }
/ ✅ 仅动画化需要的属性 /
.card { transition: transform 0.3s, box-shadow 0.3s; }
all可能导致颜色、背景、边框变化时出现意外动画。
React/框架陷阱
退出动画需要AnimatePresence:
jsx
/ ❌ 退出动画永远不会播放 /
{isVisible && }
/ ✅ 包裹条件渲染 /
{isVisible && }
列表动画使用稳定的key:
jsx
/ ❌ 索引key导致不稳定的动画 /
{items.map((item, i) =>
{item})}
/ ✅ 稳定的ID /
{items.map(item =>
{item.text})}
AutoAnimate父元素必须无条件渲染:
jsx
/ ❌ ref无法附加到条件元素 /
{showList &&
}
/ ✅ 父元素始终渲染,子元素条件渲染 /
{showList && items.map(...)}
库选择
| 库 | 大小 | 最适合 |
|---|
| 纯CSS | 0kb | 悬停状态、简单过渡 |
| AutoAnimate |
3kb | 列表、手风琴、提示消息(90%的UI动画) |
| Motion | 22kb | 手势、物理效果、滚动动画、复杂编排 |
| GSAP | 60kb | 时间线、创意动画、滚动触发序列 |
从CSS开始。列表动画添加AutoAnimate。仅在复杂需求时使用Motion/GSAP。
常见错误
- - 使用width/height动画而非scale——导致布局抖动
- 无限动画没有暂停控制——无法停止
- 进入和退出使用相同的缓动——进入用ease-out,退出用ease-in
- 忽略prefers-reduced-motion——导致身体不适
- 持续时间超过500ms——感觉迟钝
- transition: all捕获非预期属性
- React中缺少AnimatePresence实现退出动画