关于 frontend-ui-animator
面向前端开发者的 UI 动画设计与实现技能,按分析、规划、实现和验证组织工作。内容强调性能与减少动态效果的无障碍支持,并按场景选择 CSS、Tailwind 或动画库。
主要功能
- 01按阶段审查并规划动画
- 02提供常见触发方式与动画模式
- 03支持减少动态效果设置
- 04依据复杂度选择实现技术
适用场景
- 01为页面组件规划动画
- 02实现滚动显示或悬停反馈
- 03检查动画性能与无障碍支持
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ julianromli/ ai-skills --skill frontend-ui-animator安装后在 Claude Code 中输入/frontend-ui-animator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animation-patterns.mdcomponent-checklist.mdtailwind-presets.md详细介绍
前端 UI 动画设计
实现有目的且高性能的动画,在提升 UX 的同时避免让用户感到眼花缭乱。聚焦于关键时刻:主视觉开场、悬停反馈、内容显示和导航过渡。
核心理念
“无需处处都使用动画”——优先考虑:
| 优先级 | 领域 | 目的 |
|---|---|---|
| 1 | 主视觉开场 | 留下第一印象,展现品牌个性 |
| 2 | 悬停交互 | 提供反馈,提升可发现性 |
| 3 | 内容显示 | 引导注意力,降低认知负担 |
| 4 | 背景效果 | 营造氛围,增加层次感 |
| 5 | 导航过渡 | 建立空间感,保持连贯性 |
工作流
按顺序执行各阶段。完成当前阶段后再继续。
阶段 1:分析
- 扫描项目结构——找出
app/中的所有页面和components/中的所有组件 - 检查现有配置——查看
tailwind.config.ts中已有的动画和关键帧 - 确定动画候选对象——按优先级类别列出组件
- 记录限制条件——注明已安装的动画库(framer-motion 等)
输出:动画审查表。参见 references/component-checklist.md。
阶段 2:规划
- 将动画映射到组件——为组件分配具体的动画模式
- 确定触发方式——加载、滚动(交叉观察)、悬停、点击
- 估算工作量——低(仅 CSS)、中(需要钩子)、高(需要库)
- 提出分阶段发布方案——优先处理快速见效的改动
输出:包含组件 → 动画映射关系的实施计划。
阶段 3:实施
- 扩展 Tailwind 配置——添加关键帧和动画工具类
- 支持减少动态效果——优先考虑无障碍性
- 创建可复用的钩子——如有需要,创建
useScrollReveal、useMousePosition - 为各组件应用动画——遵循
references/animation-patterns.md中的模式
性能规则:
// ✅ DO: Use transforms and opacity only
transform: translateY(20px);
opacity: 0.5;
filter: blur(4px);
// ❌ DON'T: Animate layout properties
margin-top: 20px;
height: 100px;
width: 200px;
阶段 4:验证
- 在浏览器中测试——对所有动画进行视觉质量检查
- 测试减少动态效果——确认
prefers-reduced-motion有效 - 检查 CLS——确保动画不会导致布局偏移
- 性能审查——确保滚动动画不会卡顿
快速参考
动画触发方式
| 触发方式 | 实现方法 |
|---|---|
| 页面加载 | 使用 CSS animation,通过 animation-delay 实现交错效果 |
| 滚动进入视口 | 使用 IntersectionObserver 或 react-intersection-observer |
| 悬停 | 使用 Tailwind hover: 工具类或 CSS :hover |
| 点击/轻触 | 使用 useState 驱动状态 |
常见模式
子元素交错显示:
{items.map((item, i) => (
<div
key={item.id}
style={{ animationDelay: `${i * 100}ms` }}
className="animate-fade-slide-in"
/>
))}
滚动显示钩子:
const useScrollReveal = (threshold = 0.1) => {
const ref = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => entry.isIntersecting && setIsVisible(true),
{ threshold }
);
if (ref.current) observer.observe(ref.current);
return () => observer.disconnect();
}, [threshold]);
return { ref, isVisible };
};
用法:
const { ref, isVisible } = useScrollReveal();
<div ref={ref} className={isVisible ? 'animate-fade-in' : 'opacity-0'} />
资源
- 动画模式:参见
references/animation-patterns.md - 审查模板:参见
references/component-checklist.md - Tailwind 预设:参见
references/tailwind-presets.md
技术栈
- CSS 动画:简单效果的默认选择
- Tailwind 工具类:用于悬停状态和基础动画
- Framer Motion:用于复杂编排、手势和布局动画
- GSAP:用于基于时间轴的序列(如果已安装)
无障碍性(必需)
始终在全局 CSS 中添加:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}
评论
支持 Markdown