mcpField
W
web-animation-css-animations

web-animation-css-animations

github.com/agents-inc设计与 UI26100 次安装2 天前更新
代码仓库

关于 web-animation-css-animations

面向界面开发者的 CSS 动画参考技能,说明何时使用过渡、关键帧或滚动时间线,并关注渲染开销与减少动态效果偏好。

主要功能

  1. 01选择过渡或关键帧动画
  2. 02滚动与视口驱动的动画
  3. 03合成器友好的动画模式
  4. 04处理减少动态效果偏好
  5. 05缓动与时长指导

适用场景

  1. 01制作悬停和焦点状态动画
  2. 02创建加载旋转与入场效果
  3. 03构建滚动联动进度指示器
  4. 04支持减少动态效果偏好

安装

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

$npx skills add https://github.com/agents-inc/skills --skill web-animation-css-animations

安装后在 Claude Code 中输入/web-animation-css-animations确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

metadata.yaml
reference.md
examples/
core.md
keyframes.md
transitions.md

详细介绍

CSS 动画模式

**快速指南:**过渡用于承载状态变化(悬停、聚焦、切换属性);@keyframes 用于承载循环播放、自动播放或超过两个阶段的运动;animation-timeline 用于承载与滚动和视口关联的进度。将动画限制在 transform 和 opacity 上,可让帧在合成线程上运行,并且每个动画都要提供 prefers-reduced-motion 分支。

详细资源:

  • examples/core.md — 令牌系统、交互状态、入场、加载旋转图标、提示框、减少动态效果
  • examples/transitions.md — 多属性过渡、交错延迟、手风琴、颜色、链接
  • examples/keyframes.md — 滚动驱动时间线、@property 渐变、打字机、交错、clip-path 变形
  • reference.md — 缓动曲线目录、属性开销表、时长指南、浏览器支持

适用的路径

  • 运动是状态变化 — :hover、:focus-visible、数据属性、切换的类 —
    那么在基础规则上使用 transition 就是完整机制;请参阅 examples/transitions.md。
  • 运动会循环播放、在挂载时自动播放,或经过超过两个状态 — 那么就需要 @keyframes 和 animation 简写属性;请参阅 examples/keyframes.md。
  • 运动会跟踪滚动位置或视口进入状态 — 那么驱动方式应为 animation-timeline: scroll() 或 view(),而不是时间,并且关键帧描述从 0 到 1 的进度; 请参阅 examples/keyframes.md。

<critical_requirements>

编写 CSS 动画代码前

**对 transform 和 opacity 设置动画。**两者都会进行合成,因此帧能在主线程之外运行,即使标签页繁忙也能继续;而 width、top 和 margin 会在每一帧重新执行布局。

**为每个动画提供 prefers-reduced-motion 分支。**这项偏好是用于保障前庭系统安全的设置,而不是关闭开关——缩短时长的透明度渐变通常就能满足要求,同时让状态变化清晰可辨。

**入场使用 ease-out,退场使用 ease-in。**元素进入时会减速并停在目标位置,离开时会加速远去;除持续旋转以外,linear 看起来都会很机械。

**将 will-change 限定在需要它的交互范围内。**只要规则生效,每个声明都会保留一个合成层,因此全局选择器会同时为页面上的每个元素保留一个合成层。

</critical_requirements>


自动检测: @keyframes、transition-property、transition-duration、animation-timeline、 scroll-timeline、view-timeline、animation-range、animation-fill-mode、prefers-reduced-motion、 will-change、cubic-bezier、linear()、@property、steps()、transform-origin

适用于:

  • 由伪类、数据属性或切换的类驱动的状态变化运动
  • 自主运动 — 加载旋转图标、脉冲、微光、提示注意
  • 与滚动关联的进度和视口进入进度
  • 由页面已有类或属性触发的入场和退场运动

其他部分处理:

  • 运行时的播放控制 — 暂停、反向、跳转或读取进度。CSS 声明不会暴露控制句柄;可通过 Web Animations API 获取,方式是调用 element.animate(),或对 CSS 已声明的动画调用 element.getAnimations()
  • 中断时速度会延续的运动,例如手势中途接续的弹簧动画
  • 指针跟踪拖动,其中动画值就是指针位置本身
  • 在导航或视图切换期间,将退出视图和进入视图合成在一起

<decision_framework>

缓动选择

Element entering        -> ease-out (fast start, slow settle)
Element exiting         -> ease-in (slow start, fast departure)
Symmetric motion        -> ease-in-out
Continuous rotation     -> linear
Playful, overshooting   -> cubic-bezier with a control point past 1
Anything else           -> ease-out

浏览器默认的 ease 足够通用,以至于两个相邻动画使用它时会显得毫不相关;应明确指定曲线。

CSS 能表达什么

  • 滚动和视口进度 — 使用 animation-timeline: scroll() 或 view(),并通过 animation-range 决定进度的起点和终点
  • 跨元素排序 — 根据 --index 自定义属性计算 animation-delay,并使用 backwards 填充模式,使动画开始前的状态在延迟期间保持不变
  • 运行时计算的值 — 将它们写入自定义属性;动画本身仍保持声明式,并在每一帧读取该属性
  • 超调和任意曲线 — 使用超出 0–1 范围的 cubic-bezier,或使用带有点列表的 linear(),表示任何三次贝塞尔曲线都无法表示的曲线

</decision_framework>


核心模式

模式 1:动画令牌系统

将时长、缓动和移动距离定义为自定义属性,让各组件的运动保持一致,并可在一处统一调整。

:root {
  --duration-fast: 150ms;
  --duration-normal: 250ms;
  --ease-out: cubic-bezier(0, 0, 0.2, 1); /* enter */
  --ease-in: cubic-bezier(0.4, 0, 1, 1); /* exit */
  --ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* overshoot */
  --lift-md: -4px;
}

完整代码:examples/core.md


模式 2:仅合成器过渡

为每个过渡属性指定名称,并使用 transform 表示移动和尺寸变化,避免任何帧触发布局计算。

.card {
  transition:
    transform var(--duration-fast) var(--ease-out),
    opacity var(--duration-fast) var(--ease-out);
}
.card:hover {
  transform: translateY(var(--lift-md)) scale(1.02);
}

用 translate() 替代 top/left,用 scale() 替代 width/height,并用 opacity 会产生动画的伪元素替代动画 box-shadow。

完整代码:examples/core.md


模式 3:首选减少动态效果

有两种形式。渐进增强将静止状态设为基础,并选择性启用动态效果,因此之后添加的动画也不会绕过检查:

.element {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: no-preference) {
  .element {
    animation: fade-slide-in var(--duration-normal) var(--ease-out);
  }
}

优雅降级默认播放动画,并在 reduce 条件下覆盖样式——当减少动态效果的形式是更短的淡出,而非完全不动时,这种方式更合适:

@media (prefers-reduced-motion: reduce) {
  .notification {
    animation: fade-in calc(var(--notification-duration) * 0.5) var(--ease-out);
  }
}

减少动态效果并不意味着没有动画。透明度通常是安全的;需要替换的是空间移动、缩放和旋转。

完整代码:examples/core.md


模式 4:@keyframes

适用于循环播放、挂载时自动播放,或经过两个以上状态的动态效果。

@keyframes fade-slide-in {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.modal {
  animation: fade-slide-in var(--modal-enter-duration) var(--ease-out) forwards;
}

forwards 会在动画运行结束后保持最终状态;backwards 会在 animation-delay 期间显示初始状态。

完整代码:examples/core.md 和 examples/keyframes.md


模式 5:限定 will-change 的作用范围

will-change 会将元素提升到独立的合成层,这会消耗 GPU 内存,且消耗量与元素的绘制面积成正比。应在即将播放动画的规则中声明它。

.card:hover {
  will-change: transform;
}

完整代码:examples/core.md


模式 6:滚动驱动动画

animation-timeline 根据滚动进度驱动关键帧,而不是根据经过的时间驱动,因此无需滚动监听器,也无需逐帧运行 JavaScript。

.progress-bar {
  animation: grow-width linear;
  animation-timeline: scroll();
}

@keyframes grow-width {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

scroll() 跟踪滚动容器的位置;view() 跟踪元素自身经过视口的过程,并由 animation-range 限定范围。

浏览器支持: Chrome/Edge 115+、Safari 26+、Firefox 需启用标志。

完整代码:examples/keyframes.md


模式 7:使用 @property 实现自定义属性动画

注册自定义属性会为其指定类型,使其可以进行插值——渐变角度和颜色停止点只有在注册后才能播放动画。

@property --gradient-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes rotate-gradient {
  to {
    --gradient-angle: 360deg;
  }
}

浏览器支持: Chrome/Edge 85+、Safari 16.4+、Firefox 128+。

完整代码:examples/keyframes.md


<red_flags>

危险信号

运行时会出问题:

  • transition: all — 会影响后续编辑新增的所有属性,包括触发布局的属性——明确列出每个要过渡的属性
  • 为 width、height、top、left、margin 或 padding 添加动画——每一帧都会重新运行布局;主线程一忙就会丢帧——改为为 transform 添加动画,并保持布局不变
  • 为 box-shadow 添加动画——每一帧都会重新绘制元素及其阴影——改为为承载阴影的伪元素的 opacity 添加动画
  • 在永久性或宽泛的选择器上设置 will-change——每个匹配元素都会占用一个合成层;在移动设备上,合成层过多会耗尽 GPU 内存并导致标签页崩溃——仅在交互规则中声明
  • 动画没有 prefers-reduced-motion 分支——用户已在操作系统中选择减少动画,却仍会看到完整幅度的动效——编写动画时就添加该分支,不要事后补上
  • 入场动画没有 forwards——最后一帧结束后,元素会跳回动画前的状态——添加填充模式

容易出乎意料的行为:

  • 祖先元素上的 transform 会创建包含块,因此 position: fixed 的后代元素会锚定到该祖先,而不是视口
  • will-change 会创建层叠上下文,从而改变 z-index 相对于同级元素的解析方式
  • 如果没有 animation-fill-mode: backwards,带延迟的动画会在延迟期间渲染最终状态,而不是第一帧
  • display: none 无法添加动画——改用 opacity 搭配 visibility,或让 grid-template-rows 从 0fr 动画到 1fr
  • SVG 路径绘制应为 stroke-dasharray 和 stroke-dashoffset 添加动画;transform 移动的是路径,而不是绘制路径
  • scroll() 时间线需要可滚动的祖先元素——overflow: hidden 的父元素不会产生进度
  • 打印时不会运行动画,因此动画前的状态必须在纸面上清晰可读
  • 时长超过约 1 秒会显得迟缓,而非从容

评论

支持 Markdown