mcpField
A
animation-best-practices

animation-best-practices

github.com/millionco设计与 UI15.1k200 次安装2 周前更新
代码仓库

关于 animation-best-practices

面向界面动画实现者的实用参考技能,涵盖时长、缓动、交互反馈、悬停行为、无障碍和调试,并提供 CSS 示例与建议。

主要功能

  1. 01录制并检查动画表现
  2. 02选择时长与缓动曲线
  3. 03设计按钮和弹出层过渡
  4. 04避免移动元素导致悬停闪烁
  5. 05兼顾触屏与点击区域尺寸

适用场景

  1. 01审查新界面中的动效
  2. 02改善按钮和弹出层反馈
  3. 03排查动画抖动或悬停闪烁

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/millionco/react-doctor --skill animation-best-practices

安装后在 Claude Code 中输入/animation-best-practices确认已加载。

详细介绍

实用动画技巧

常见动画场景的详细参考指南。实现动画时,可将其用作检查清单。

录制与调试

录制动画

如果感觉动画不太对劲,却找不出原因,可以录制动画并逐帧回放。这样能发现正常速度下看不到的细节。

修复动画抖动

由于 GPU/CPU 渲染交接,CSS 变换动画可能会在开始或结束时让元素偏移 1px。

修复方法:

.element {
  will-change: transform;
}

这样可以让浏览器在整个动画过程中都将元素保留在 GPU 上。

适当休息

不要一口气编写并发布动画。停下来休息一下,再以全新的眼光审视。优秀的动画会经过数天的评审和打磨,而不是几个小时。

按钮与点击反馈

按下时缩放按钮

添加轻微的缩放反馈,让界面感觉更灵敏:

button:active {
  transform: scale(0.97);
}

这样可以立即提供视觉反馈,让用户知道界面正在响应。

不要从 scale(0) 开始动画

从 scale(0) 开始会让元素凭空出现,感觉不自然。

不佳:

.element {
  transform: scale(0);
}
.element.visible {
  transform: scale(1);
}

推荐:

.element {
  transform: scale(0.95);
  opacity: 0;
}
.element.visible {
  transform: scale(1);
  opacity: 1;
}

元素应始终保留一定的可见形状,就像尚未充气的气球。

工具提示与弹出框

后续工具提示跳过动画

第一个工具提示:延迟显示并播放动画。后续工具提示(已有一个打开时):立即显示,不延迟。

.tooltip {
  transition:
    transform 125ms ease-out,
    opacity 125ms ease-out;
  transform-origin: var(--transform-origin);
}

.tooltip[data-starting-style],
.tooltip[data-ending-style] {
  opacity: 0;
  transform: scale(0.97);
}

/* Skip animation for subsequent tooltips */
.tooltip[data-instant] {
  transition-duration: 0ms;
}

Radix UI 和 Base UI 可通过 data-instant 属性支持此模式。

根据触发位置调整动画

弹出框应从触发器的位置缩放,而不是从中心缩放。

/* Default (wrong for most cases) */
.popover {
  transform-origin: center;
}

/* Correct - scale from trigger */
.popover {
  transform-origin: var(--transform-origin);
}

Radix UI:

.popover {
  transform-origin: var(--radix-dropdown-menu-content-transform-origin);
}

Base UI:

.popover {
  transform-origin: var(--transform-origin);
}

速度与时长

保持动画快速

即使加载时间相同,旋转更快的加载指示器也会让应用显得更快。时长为 180ms 的选择动画比 400ms 的感觉更灵敏。

规则: UI 动画应控制在 300ms 以内。

不要为键盘交互添加动画

方向键导航、键盘快捷键——这些操作每天会重复数百次。添加动画会让它们显得迟缓且脱节。

绝不要为以下操作添加动画:

  • 使用方向键进行列表导航
  • 键盘快捷键响应
  • 标签页/焦点移动
谨慎处理频繁使用的元素

悬停效果虽然不错,但如果每天触发多次,完全不添加动画可能更合适。

建议: 每天使用自己的产品。通过反复使用,你会发现哪些动画会变得烦人。

悬停状态

修复悬停闪烁

悬停动画改变元素位置时,光标可能会移出元素,导致闪烁。

问题:

.box:hover {
  transform: translateY(-20%);
}

解决方案: 改为为子元素添加动画:

<div class="box">
  <div class="box-inner"></div>
</div>
.box:hover .box-inner {
  transform: translateY(-20%);
}

.box-inner {
  transition: transform 200ms ease;
}

父元素的悬停区域保持稳定,同时子元素移动。

在触屏设备上禁用悬停

触屏设备没有真正的悬停。手指意外移动可能会触发不需要的悬停状态。

@media (hover: hover) and (pointer: fine) {
  .card:hover {
    transform: scale(1.05);
  }
}

注意: Tailwind v4 的 hover: 类会自动仅在设备支持悬停时生效。

触控与无障碍

确保目标区域大小合适

小按钮难以点击。使用伪元素扩大点击区域,而不改变布局。

目标区域最小尺寸: 44px(Apple 和 WCAG 建议)

@utility touch-hitbox {
  position: relative;
}

@utility touch-hitbox::before {
  content: "";
  position: absolute;
  display: block;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  min-height: 44px;
  min-width: 44px;
  z-index: 9999;
}

用法:

<button className="touch-hitbox">
  <BellIcon />
</button>

缓动效果选择

进入/退出使用 ease-out

进入或退出的元素应使用 ease-out。快速开始会带来灵敏的感觉。

.dropdown {
  transition:
    transform 200ms ease-out,
    opacity 200ms ease-out;
}

ease-in 的起步较慢,不适合 UI。即使时长相同,运动也会显得更慢,因为运动主要集中在后半段。

屏幕内移动使用 ease-in-out

对于已经可见且需要移动的元素,应使用 ease-in-out。它能模拟汽车般自然的加速和减速。

.slider-handle {
  transition: transform 250ms ease-in-out;
}
使用自定义缓动曲线

内置 CSS 曲线通常不够理想。自定义曲线能让运动效果更有设计感。

资源:

视觉技巧

将模糊用作备用方案

当缓动和时间调整无法解决问题时,可以添加轻微的模糊来掩盖瑕疵。

.button-transition {
  transition:
    transform 150ms ease-out,
    filter 150ms ease-out;
}

.button-transition:active {
  transform: scale(0.97);
  filter: blur(2px);
}

模糊能衔接不同状态之间的视觉间隙,让眼睛误以为过渡更平滑。两个状态会融合在一起,而不会显得像两个独立的对象。

性能提示: 尤其是在 Safari 上,模糊程度应保持在 20px 以下。

细节为何重要

“所有那些不为人知的细节汇聚在一起,创造出令人惊叹的事物,就像一千个几不可闻的声音齐声歌唱,音调和谐。” — Paul Graham,《黑客与画家》

好的细节往往不会引人注意——用户可以毫无阻碍地完成任务。优秀的界面能让用户轻松实现目标,而不是让他们去欣赏动画。

评论

支持 Markdown