Transitions.dev
12 个可移植的 CSS 过渡效果,每个均使用 t-* 选择器命名空间并搭配语义化的 CSS 自定义属性。即插即用:粘贴代码片段,连接文档中说明的 HTML 钩子,即可完成。不依赖任何框架,不包含演示专用标记,每个片段都内置了 prefers-reduced-motion 保护。
快速参考
| 过渡效果 | 适用场景 | 参考文件 |
|---|---|---|
| 卡片尺寸变化 | 当容器布局状态改变时,调整其宽度或高度。 | 01-card-resize.md |
| 数字弹出 | 当数字更新时,每个数字以模糊滑动的方式重新进入。 | 02-number-pop-in.md |
| 通知徽章 | 将小徽章滑动到触发器上,弹出圆点。 | 03-notification-badge.md |
| 文本状态切换 | 以模糊的上下过渡效果原地切换文本。 | 04-text-states-swap.md |
| 菜单下拉菜单 | 打开一个从触发器位置展开的、感知原点的下拉菜单。 | 05-menu-dropdown.md |
| 模态框打开/关闭 | 模态对话框以缩放方式打开,关闭时以更柔和的缩放方式缩小。 | 06-modal.md |
| 面板展开 | 将面板以交叉模糊效果滑入某个区域。 | 07-panel-reveal.md |
| 页面左右切换 | 在两个并排页面之间滑动切换(列表 ↔ 详情,步骤 1 ↔ 步骤 2)。 | 08-page-side-by-side.md |
| 图标切换 | 在同一位置以模糊和缩放效果交叉淡入淡出两个图标。 | 09-icon-swap.md |
| 成功勾选 | 结合淡入、旋转、Y 轴弹跳和路径描边绘制,庆祝操作完成。 | 10-success-check.md |
| 头像组悬停 | 在一行项目上实现距离衰减抬起效果,鼠标离开时带有弹跳回位。 | 11-avatar-group-hover.md |
| 错误状态抖动 | 分段三次贝塞尔曲线抖动,并自动恢复边框和提示信息。 | 12-error-state-shake.md |
决策规则
当用户请求一个过渡效果时,首先匹配可见的 UI 元素,然后匹配操作动词:
- 触发器 + 浮动在其上的小圆点 → 通知徽章。
- 触发器 + 从其展开的表面 → 下拉菜单(锚定,感知原点)或模态框(居中,无锚点)。
- 滑入页面某个区域的表面 → 面板展开。
- 两个屏幕,列表 ↔ 详情或步骤 1 ↔ 步骤 2 → 页面左右切换。
- 元素改变宽度或高度 → 卡片尺寸变化。
- 元素文本内容原地改变 → 文本状态切换。
- 同一位置的两个图标 → 图标切换。
- 数字更新 → 数字弹出。
- 确认/成功/“完成”时刻(勾选标记、支付成功、文件上传)→ 成功勾选。
- 水平堆叠中的项目悬停(头像、芯片、分段按钮、标签药丸)→ 头像组悬停。
- 表单验证错误/“这有问题”反馈(无效字段、错误 PIN、重复名称)→ 错误状态抖动。
- 无明确匹配 → 回退到
transitions reveal(列出所有过渡),让用户选择。不要猜测。
如果两个过渡都可能匹配,优先选择开销较小的一个(卡片尺寸变化优于面板展开,下拉菜单优于模态框,成功勾选优于完整的模态庆祝),除非设计明确需要使用更重的表面。成功勾选仅包含动画——如果还需要从旋转器切换到勾选标记,请与图标切换配合使用。
命令
技能额外暴露三个命名空间下的动词,代理应能识别这些命令以及直接的过渡请求。每个命令都以 transitions 开头,确保调用不会与项目中安装的其他技能的命令冲突。
transitions reveal — 列出所有过渡效果
触发短语: transitions reveal、"reveal the transitions"、"list all transitions"、"what transitions are in this skill"、"show the transitions catalog"。
行为: 以编号的纯文本列表形式打印 12 个过渡效果——名称、一行摘要以及匹配的参考文件名。复用上方 ## 快速参考 中的内容;不要自行编造。无需访问项目。
transitions review — 审计项目适用性
触发短语: transitions review、"review my project"、"audit my animations"、"where would transitions.dev help"、"find places to use this skill"。
行为:
- 在工作区中搜索指示符:
transition:声明、@keyframes、样式文件中的硬编码ms/s持续时间、匹配 11 种决策规则模式(模态框、下拉菜单、徽章等)的组件。 - 对于每个匹配项,对照决策规则,选择唯一的最佳匹配过渡。
- 按文件分组输出编号列表:
path/to/Component.tsx:42— 看起来是下拉菜单打开,建议使用 menu-dropdown(05-menu-dropdown.md)。- 跳过已经使用
t-*类的 ad-hoc 过渡。
- 不进行任何编辑。以"运行
transitions apply在任意行上安装建议的过渡效果。"结束。
transitions apply — 安装最佳匹配的过渡效果
触发短语: transitions apply、"apply a transition here"、"add the right transition"、"install transitions-dev here"、"fix the animation on this element"。
行为:
- 读取上下文:当前打开的文件、光标附近的元素、周围的 CSS / JSX。如果用户明确指定了过渡名称(例如
transitions apply menu-dropdown),则使用该名称。 - 对该上下文运行
## 决策规则中的规则,选择一个过渡。如果两个都可能匹配,优先选择开销较小的一个(与现有规则相同的平局判定标准)。 - 显示一行提议:"我建议在这里应用 menu-dropdown,因为该元素从触发器打开并且是锚定的。确认安装?"。
- 确认后,严格遵守
## 输出格式中的现有五步流程(根块、代码片段、钩子、减少运动保护、JS 编排(如需要))。 - 如果代理无法自信地选择一个过渡,则回退到
transitions reveal并请用户选择。
通用安装
将以下 :root 块一次性复制到你的项目中。每个过渡片段都从这些语义名称读取值——后续无需再追踪每个组件的值。
/* transitions-dev — 将此 :root 块一次性复制到你的项目中。
每个过渡片段都从这些语义名称读取值。 */
:root {
/* 卡片尺寸变化 */
--resize-dur: 300ms;
--resize-ease: cubic-bezier(0.22, 1, 0.36, 1);
/* 数字弹出 */
--digit-dur: 500ms;
--digit-distance: 8px;
--digit-stagger: 70ms;
--digit-blur: 2px;
--digit-ease: cubic-bezier(0.34, 1.45, 0.64, 1);
--digit-dir-x: 0;
--digit-dir-y: 1;
/* 通知徽章 */
--badge-slide-dur: 260ms;
--badge-pop-dur: 500ms;
--badge-pop-close-dur: 180ms;
--badge-fade-dur: 400ms;
--badge-fade-close-dur: 180ms;
--badge-blur: 2px;
--badge-offset-x: -8.2px;
--badge-offset-y: 12.4px;
--badge-slide-ease: cubic-bezier(0.22, 1, 0.36, 1);
--badge-pop-ease: cubic-bezier(0.34, 1.36, 0.64, 1);
--badge-close-ease: cubic-bezier(0.4, 0, 0.2, 1);
/* 文本状态切换 */
--text-swap-dur: 150ms;
--text-swap-translate-y: 4px;
--text-swap-blur: 2px;
--text-swap-ease: ease-in-out;
/* 菜单下拉菜单 */
--dropdown-open-dur: 250ms;
--dropdown-close-dur: 150ms;
--dropdown-pre-scale: 0.97;
--dropdown-closing-scale: 0.99;
--dropdown-ease: cubic-bezier(0.22, 1, 0.36, 1);
/* 模态框打开/关闭 */
--modal-open-dur: 250ms;
--modal-close-dur: 150ms;
--modal-scale: 0.96;
--modal-scale-close: 0.96;
--modal-ease: cubic-bezier(0.22, 1, 0.36, 1);
/* 面板展开 */
--panel-open-dur: 400ms;
--panel-close-dur: 350ms;
--panel-translate-y: 100px;
--panel-blur: 2px;
--panel-ease: cubic-bezier(0.22, 1, 0.36, 1);
/* 页面左右切换 */
--page-slide-dur: 200ms;
--page-fade-dur: 200ms;
--page-slide-distance: 8px;
--page-blur: 3px;
--page-stagger: 0ms;
--page-exit-enabled: 1;
--page-slide-ease: cubic-bezier(0.22, 1, 0.36, 1);
--page-fade-ease: cubic-bezier(0.22, 1, 0.36, 1);
/* 图标切换 */
--icon-swap-dur: 200ms;
--icon-swap-blur: 2px;
--icon-swap-start-scale: 0.25;
--icon-swap-ease: ease-in-out;
/* 成功勾选 */
--check-opacity-dur: 550ms;
--check-rotate-dur: 550ms;
--check-rotate-from: 80deg;
--check-bob-dur: 450ms;
--check-y-amount: 40px;
--check-blur-dur: 500ms;
--check-blur-from: 10px;
--check-path-dur: 550ms;
--check-path-delay: 80ms;
--check-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
--check-ease-opacity: cubic-bezier(0.22, 1, 0.36, 1);
--check-ease-rotate: cubic-bezier(0.22, 1, 0.36, 1);
--check-ease-bob: cubic-bezier(0.34, 1.35, 0.64, 1);
--check-ease-path: cubic-bezier(0.22, 1, 0.36, 1);
/* 头像组悬停 */
--avatar-lift: -4px;
--avatar-dur: 320ms;
--avatar-scale: 1.05;
--avatar-falloff: 0.45;
--avatar-ease-in: cubic-bezier(0.22, 1, 0.36, 1);
--avatar-ease-out: cubic-bezier(0.34, 3.85, 0.64, 1);
/* 错误状态抖动 */
--shake-distance: 6px;
--shake-overshoot: 4px;
--shake-dur-a: 80ms;
--shake-dur-b: 60ms;
--shake-ease: cubic-bezier(0.22, 1, 0.36, 1);
--revert-hold: 3000ms;
--revert-dur: 280ms;
}
演示站点 transitions.dev 使用的 --pX-* 源标记不在此处导出。可调值已重命名为语义名称(--badge-*、--dropdown-*、--modal-*等),以便用户拥有设计词汇。
输出格式
当将过渡效果插入用户的项目时:
- 将上面的
:root块添加到用户的全局样式表,但仅当它尚未存在时才添加。如果用户已经导入了一次通用安装块,不要重复添加。 - 从相关的参考文件中逐字粘贴所选过渡效果的 CSS。不要重写选择器,不要将过渡压缩为简写形式,不要移除
will-change。这些代码片段已经过调整和测试。 - 连接文档中说明的 HTML 钩子——类名(
.t-dropdown、.t-modal、.t-success-check、.t-avatar、.t-input等)和状态属性(data-open、data-state、data-page、.is-open、.is-closing、.is-exit、.is-enter-start、.is-animating、.is-error、.is-shaking)。 - 保留
@media (prefers-reduced-motion: reduce)块。每个片段都内置了它。移除它会导致组件无法通过可访问性审计。 - 对于需要 JS 的过渡(下拉菜单、模态框、文本切换、数字弹出、页面滑动、成功勾选、头像组悬停、错误状态抖动),从参考文件中复制小的编排代码片段,并将选择器适配到用户的 DOM。保留时间读取(
getComputedStyle(...)getPropertyValue("--…")),使持续时间与:root值保持同步。
保持差异最小:仅编辑引入过渡所需的文件。不要重命名用户现有的变量,不要重新格式化不相关的 CSS,不要引入运动库。
应避免的常见错误
- 省略关闭状态类的清理——对于下拉菜单/模态框,如果没有移除
.is-closing的setTimeout,下一次打开将从结束缩放比例开始,而不是从静态的打开前缩放比例。 - 忘记回流——在文本切换、数字弹出、成功勾选重放和错误状态抖动中,在移除和重新添加类/属性之间使用
void el.offsetWidth(或offsetHeight)是保证动画重放的关键。 - 动画化单个容器而不是内部组成部分——对于徽章,动画化圆点,而不是触发器;对于页面滑动,动画化页面部分,而不是容器。
- 将
transition: …替换为transition: all——每个片段都特意枚举了确切的属性,以防止无关的样式变化被意外包含。 - 硬编码成功勾选的
stroke-dasharray——代码片段中使用了20作为占位符。请将其替换为path.getTotalLength()向上取整加 1,以匹配你自己的路径,否则描边会提前显示或过度绘制。 - 在 CSS 中设置
transition-timing-function用于头像组悬停——必须在 JS 中内联设置,并且要在--shift/--scale-active写入之前,这样弹性缓出才仅适用于mouseleave。 - 将
.is-error和.is-shaking混合成一个类用于错误状态抖动——保持它们正交,这样才能在不闪烁整个错误处理的情况下重放抖动(移除 → 回流 → 重新添加)。
参考文件
- 01-card-resize.md — 卡片尺寸变化
- 02-number-pop-in.md — 数字弹出
- 03-notification-badge.md — 通知徽章
- 04-text-states-swap.md — 文本状态切换
- 05-menu-dropdown.md — 菜单下拉菜单
- 06-modal.md — 模态框打开/关闭
- 07-panel-reveal.md — 面板展开
- 08-page-side-by-side.md — 页面左右切换
- 09-icon-swap.md — 图标切换
- 10-success-check.md — 成功勾选
- 11-avatar-group-hover.md — 头像组悬停
- 12-error-state-shake.md — 错误状态抖动
- _root.css — 独立的通用安装块,可直接导入。