关于 kinetic-typography
kinetic-typography 是一套动态文字设计技能,面向网页和视频标题、字幕及歌词动画制作。它涵盖逐行、逐词和逐字拆分与多种揭示效果,并提供可运行代码及无障碍和画面验证指导。
主要功能
- 01按行、词或字符拆分文本
- 02制作遮罩、模糊及剪切揭示效果
- 03为可变字体制作字重动画
- 04支持网页、Remotion 和 After Effects 方案
- 05提供无障碍与定格画面验证指导
适用场景
- 01制作网页标题和标语入场动画
- 02设计歌词视频与字幕揭示效果
- 03为可变字体添加动态效果
- 04制作文字沿路径移动或描边显现效果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ iart-ai/ kinetic-typography-skills --skill kinetic-typography安装后在 Claude Code 中输入/kinetic-typography确认已加载。
附带文件README.mdreferences/reveal-recipes.md
详细介绍
动态排版
富有表现力地为文本添加动画:将文案拆分为行、单词或字符,错开显示、遮罩、模糊、字重变形,并让文字沿路径运行。可生成适用于网页(CSS、GSAP、Framer Motion)和视频(Remotion)的可运行代码,另外还提供 After Effects 表达式方案。
适用场景
- 标题/标语入场动画和动态标题卡片。
- 歌词视频、字幕显示动画、动态排版作品。
- 可变字体动画(字重、字宽、倾斜度、光学尺寸)。
- 沿路径排布文字、描边绘制效果,以及逐字符变形效果。
核心工作流程
1. 先把静态排版做好
动画无法挽救糟糕的字体排版。开始动画前,先确定行高(展示型标题为 1.1-1.2,正文为 1.4-1.6)、字距(展示型文字收紧 -1% 到 -3%,例如 letter-spacing: -0.02em)、对齐方式和字重。然后再拆分并制作动画。
2. 选择拆分粒度
- 按行 —— 最平静、最显高级;最适合多行段落和优雅的标题。
- 按单词 —— 更有活力,适合标语和歌词重点。
- 按字符 —— 动感最强、最活泼;长文案容易显得繁杂。仅用于短字符串。
工具:网页端使用 SplitType 或 GSAP SplitText;Remotion 中使用 .split('') / .split(' ') 加 interpolate;Framer Motion 中使用错开的 motion 子元素。
重要的无障碍提示:拆分为逐字符的 span 会破坏屏幕阅读器读取文本的效果,也会导致复制粘贴异常。务必在容器上设置包含完整字符串的 aria-label,并在拆分后的片段上设置 aria-hidden="true"。
3. 应用显示动画技巧
四种常用显示动画:
- 遮罩/裁剪显示(最稳健) —— 将每一行包裹在
overflow: hidden的容器中;让子元素从translateY(100%)动画到0。文字从隐藏的基线向上擦入。没有模糊伪影,GPU 开销低,是行业标准的标题显示动画。 - 模糊入场 —— 将
filter: blur(12px) -> blur(0)与opacity 0 -> 1一起制作动画。效果柔和、高级,有“拉焦”感。渲染开销较大;请保持模糊半径适中,并优先使用较短时长。 - clip-path 擦入 —— 将
clip-path: inset(0 100% 0 0)动画到inset(0 0 0 0),在不移动字形的情况下实现定向显示。 - 字符错开 —— 拆分为字符后,逐个淡入/平移,每个字符间隔 20-40ms。
4. 遵循动效原则设置时序
内联的关键要点(确保本技能可独立使用):
- 入场使用缓出:
cubic-bezier(0.16, 1, 0.3, 1)(easeOutExpo)显得高级。 - 每个片段的时长为 400-600ms。
- 错开间隔:行与行之间为 60-100ms,单词之间为 40-70ms,字符之间为 20-40ms。
- 将显示动画的总时长控制在约 800ms 以内;对于长字符串,请缩短逐字符间隔,或改用按单词/按行拆分。
5. 遮罩显示,可直接复制粘贴(原生 CSS + JS 行拆分)
<h1 class="reveal" aria-label="Designed for motion">Designed for motion</h1>
.reveal .line { overflow: hidden; }
.reveal .line > span {
display: inline-block;
transform: translateY(110%);
animation: rise 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
.reveal .line:nth-child(2) > span { animation-delay: 0.08s; }
.reveal .line:nth-child(3) > span { animation-delay: 0.16s; }
@keyframes rise { to { transform: translateY(0); } }
6. 可变字体字重动画
@keyframes thicken {
from { font-variation-settings: "wght" 200; }
to { font-variation-settings: "wght" 800; }
}
.headline {
font-family: "Inter var", sans-serif;
animation: thicken 0.8s cubic-bezier(0.65, 0, 0.35, 1) forwards;
}
为 font-variation-settings 制作动画(可涵盖任意轴:wght、wdth、slnt、opsz 以及自定义轴),不要使用 font-weight,这样才能使用非标准值并实现平滑插值。开始动画前,请确认已加载的字体确实是可变字体,并检查轴的取值范围(例如 wght 100-900),否则该值会被静默限制。
交付与验证(独立 HTML)
打包的辅助脚本(
scripts/):scripts/seek-shot.sh anim.html 0 1.5 3会冻结?t=N测试框架并截取每个时刻的画面;scripts/contact-sheet.sh sheet.png frame-*.png会将它们拼成一张图,便于一目了然地检查。参阅scripts/README.md。
对于网页文字显现/动态标题交付物,请提供一个可直接在浏览器中打开的 .html 文件——无需构建步骤。对于标题、标题卡或单次显现效果,一个文件就足够。
输出约定:
- 一个
.html文件:标记中,容器带有aria-label;显现效果写在内联<style>中(或使用一个来自 CDN 的内联 GSAP<script>)。 - 一个动画驱动方式——CSS
@keyframes显现效果,或单个 GSAP 时间轴;不要两者兼用。 - 加入下方的冻结测试框架,以便确定性地截取任意时刻的画面。
- 在
document.fonts.ready之后进行拆分,以确保冻结帧中的换行正确。
冻结测试框架——固定帧以供截图。
<script>
const t = new URLSearchParams(location.search).get("t");
if (t !== null) {
// CSS @keyframes reveal:
document.querySelectorAll(".reveal *").forEach(el => {
el.style.animationDelay = (-parseFloat(t)) + "s";
el.style.animationPlayState = "paused";
});
// GSAP timeline instead? → tl.pause(); tl.seek(parseFloat(t));
}
window.__ready = true; // ready signal for headless wait
</script>
验证流程——渲染 → 冻结 → 截图 → 检查:
- 打开文件并冻结在开始/中间/结束时刻:
…/type.html?t=0、?t=<dur/2>、?t=<dur>。 - 为每个冻结帧截图。
- 检查保真度(是否符合需求说明)和瑕疵——字形/下伸部被裁切、遮罩未能完全隐藏基线、字体加载前出现 FOUC 或换行错误、模糊边缘。
npx playwright screenshot --wait-for-timeout=500 "file://$PWD/type.html?t=0.4" frame-mid.png
完成前:
- 可在浏览器中独立打开——没有控制台错误,也没有缺失的 CDN/字体。
- 只有一个显现驱动方式;
?t=N能正确冻结精确帧。 - 已在开始/中间/结束时刻截图——没有字形被裁切或 FOUC,换行正确。
- 遵循
prefers-reduced-motion(文本显示为最终状态,不播放动画)。 - 容器带有
aria-label;拆分片段带有aria-hidden——复制内容和屏幕阅读器文本保持完整。
快速参考
| 效果 | 核心 CSS/实现方式 |
|---|---|
| 向上遮罩显现 | 父元素设为 overflow:hidden;子元素 translateY(110%)->0 |
| 模糊显现 | filter: blur(12px)->0 + 透明度 |
| 定向擦除 | clip-path: inset(0 100% 0 0)->inset(0) |
| 字符错开 | 拆分字符,间隔 20-40ms,淡入并上移 |
| 可变字重 | 动画化 font-variation-settings:"wght" a->b |
| 沿路径排布文本 | SVG <textPath href="#curve"> |
| 描边绘制 | 将 SVG 文本设为路径,动画化 stroke-dashoffset |
沿路径排布文本(SVG)
<svg viewBox="0 0 600 200">
<path id="curve" d="M20,150 Q300,20 580,150" fill="none" />
<text font-size="42" fill="#fff">
<textPath href="#curve" startOffset="0%">Follow the curve</textPath>
</text>
</svg>
动画化 startOffset 属性(0% -> 100%)可让文本沿路径滚动;也可以动画化路径 d,让文本沿变形曲线流动。
参考文件
references/reveal-recipes.md— 可直接复制粘贴的显现效果指南:CSS 中的遮罩/模糊/裁剪/字符错开、GSAP SplitText 时间轴、Framer Motion 错开变体、Remotion 逐字符插值、可变字体关键帧,以及对屏幕阅读器友好的拆分辅助函数。