看得见怎么动的网页动画

前 3 张是 workflow.maysuns.uk 首页「全景图」里的图,由 Python 生成 SVG + 纯 CSS 动画,没有任何图片文件、没有 JavaScript。下面的配方每个都是一小段独立 HTML。

① 由哪些部分组成

CLAUDE.md / Rule规矩Memory记忆Skill做事步骤Command一键流程Permission安全带MCP外接工具子 Agent / loop分身与定时AI(Claude Code)

怎么动的

  1. 中间蓝色圆是"核心",用 CSS 的 @keyframes pulse 让它在 1 倍和 1.07 倍之间来回缩放(2.4 秒一轮)。
  2. 中心到各方块的连线是虚线,动画不断改 stroke-dashoffset(0 → -24,1.4 秒循环),虚线的"起点"在移动,看起来像在流动。
  3. 每个方块是一个 <g class="sat">,用 animation-delay 错开 0.15 秒依次"弹出"(透明度 0→1,缩放 0.7→1)。
  4. 方块的位置不是手摆的:用三角函数把 7 个方块均匀放在一个圆上(角度 = i × 360° ÷ 7),所以改数量只改一个数字。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>① 由哪些部分组成</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.ovw h2{border-top:0;margin-top:8px}.ovw .card2{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;margin:14px 0}
.ovw h3{margin:0 0 6px}.ov{width:100%;height:auto;display:block;color:var(--text)}
.ov .core{animation:pulse 2.4s ease-in-out infinite;transform-origin:center;transform-box:fill-box}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
.ov .dashline{animation:dash 1.4s linear infinite}@keyframes dash{to{stroke-dashoffset:-24}}
.ov .sat{animation:pop .6s ease both;transform-box:fill-box;transform-origin:center}@keyframes pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}
.ov .sat:hover rect{opacity:.32}
.ov .runner{offset-path:path('M60 90 L840 90');offset-distance:0%;animation:run 5s linear infinite}@keyframes run{to{offset-distance:100%}}
.ov .orbit{offset-path:circle(135px at 380px 190px);animation:run 6s linear infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
@media(prefers-reduced-motion:reduce){.ov *,.can *{animation:none!important}.ov .runner,.ov .orbit{display:none}}
</style></head><body><div class="box">
<svg viewBox="0 0 760 440" class="ov" role="img" aria-label="① 由哪些部分组成"><line x1="380" y1="220" x2="380" y2="55" stroke="#2563eb" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.0s"><rect x="305" y="27" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="305" y="27" width="150" height="56" rx="14" fill="#2563eb" opacity=".14" stroke="#2563eb" stroke-width="2"/><text x="380" y="49" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">CLAUDE.md / Rule</text><text x="380" y="65" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">规矩</text></g><line x1="380" y1="220" x2="545" y2="117" stroke="#7c3aed" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.1s"><rect x="470" y="89" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="470" y="89" width="150" height="56" rx="14" fill="#7c3aed" opacity=".14" stroke="#7c3aed" stroke-width="2"/><text x="545" y="111" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">Memory</text><text x="545" y="127" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">记忆</text></g><line x1="380" y1="220" x2="586" y2="257" stroke="#059669" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.3s"><rect x="511" y="229" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="511" y="229" width="150" height="56" rx="14" fill="#059669" opacity=".14" stroke="#059669" stroke-width="2"/><text x="586" y="251" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">Skill</text><text x="586" y="267" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">做事步骤</text></g><line x1="380" y1="220" x2="472" y2="369" stroke="#d97706" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.4s"><rect x="397" y="341" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="397" y="341" width="150" height="56" rx="14" fill="#d97706" opacity=".14" stroke="#d97706" stroke-width="2"/><text x="472" y="363" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">Command</text><text x="472" y="378" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">一键流程</text></g><line x1="380" y1="220" x2="288" y2="369" stroke="#dc2626" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.6s"><rect x="213" y="341" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="213" y="341" width="150" height="56" rx="14" fill="#dc2626" opacity=".14" stroke="#dc2626" stroke-width="2"/><text x="288" y="363" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">Permission</text><text x="288" y="378" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">安全带</text></g><line x1="380" y1="220" x2="174" y2="257" stroke="#0891b2" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.8s"><rect x="99" y="229" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="99" y="229" width="150" height="56" rx="14" fill="#0891b2" opacity=".14" stroke="#0891b2" stroke-width="2"/><text x="174" y="251" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">MCP</text><text x="174" y="267" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">外接工具</text></g><line x1="380" y1="220" x2="215" y2="117" stroke="#db2777" stroke-width="2.5" stroke-dasharray="6 6" class="dashline" opacity=".7"/><g class="sat" style="animation-delay:0.9s"><rect x="140" y="89" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="140" y="89" width="150" height="56" rx="14" fill="#db2777" opacity=".14" stroke="#db2777" stroke-width="2"/><text x="215" y="111" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">子 Agent / loop</text><text x="215" y="127" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">分身与定时</text></g><circle cx="380" cy="220" r="70" fill="#2563eb" class="core"/><text x="380" y="213" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">AI</text><text x="380" y="233" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">(Claude Code)</text></svg>
</div></body></html>

② 怎么运转(小球沿线走)

1你说一句2读规矩+ 记忆3选 Skill或命令4动手干活5权限把关6写回结果+ 记忆下一轮更懂你

怎么动的

  1. 底下那条直线是 SVG 的 <path d="M60 90 L840 90">:从 (60,90) 画到 (840,90)。
  2. 小球本身是个普通圆 <circle r="7">,关键是 CSS 的 offset-path: path('M60 90 L840 90')——告诉浏览器"按这条路线走"。
  3. 再写 @keyframes run { to { offset-distance: 100% } },把 offset-distance 从 0% 推到 100%,小球就从起点走到终点(5 秒,线性,无限循环)。
  4. 要让小球走曲线/回环,只要把 path 换成曲线(C 命令)即可,不用改动画。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>② 怎么运转(小球沿线走)</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.ovw h2{border-top:0;margin-top:8px}.ovw .card2{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;margin:14px 0}
.ovw h3{margin:0 0 6px}.ov{width:100%;height:auto;display:block;color:var(--text)}
.ov .core{animation:pulse 2.4s ease-in-out infinite;transform-origin:center;transform-box:fill-box}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
.ov .dashline{animation:dash 1.4s linear infinite}@keyframes dash{to{stroke-dashoffset:-24}}
.ov .sat{animation:pop .6s ease both;transform-box:fill-box;transform-origin:center}@keyframes pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}
.ov .sat:hover rect{opacity:.32}
.ov .runner{offset-path:path('M60 90 L840 90');offset-distance:0%;animation:run 5s linear infinite}@keyframes run{to{offset-distance:100%}}
.ov .orbit{offset-path:circle(135px at 380px 190px);animation:run 6s linear infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
@media(prefers-reduced-motion:reduce){.ov *,.can *{animation:none!important}.ov .runner,.ov .orbit{display:none}}
</style></head><body><div class="box">
<svg viewBox="0 0 900 250" class="ov" role="img" aria-label="② 怎么运转"><path d="M60 90 L840 90" stroke="#94a3b8" stroke-width="3" stroke-dasharray="8 6" class="dashline" fill="none"/><g class="sat" style="animation-delay:0.0s"><rect x="1" y="55" width="118" height="70" rx="14" style="fill:var(--panel)"/><rect x="1" y="55" width="118" height="70" rx="14" fill="#2563eb" opacity=".14" stroke="#2563eb" stroke-width="2"/><circle cx="60" cy="55" r="13" fill="#2563eb"/><text x="60" y="60" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">1</text><text x="60" y="96" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">你说一句</text></g><g class="sat" style="animation-delay:0.1s"><rect x="157" y="55" width="118" height="70" rx="14" style="fill:var(--panel)"/><rect x="157" y="55" width="118" height="70" rx="14" fill="#7c3aed" opacity=".14" stroke="#7c3aed" stroke-width="2"/><circle cx="216" cy="55" r="13" fill="#7c3aed"/><text x="216" y="60" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">2</text><text x="216" y="88" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">读规矩</text><text x="216" y="104" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">+ 记忆</text></g><g class="sat" style="animation-delay:0.3s"><rect x="313" y="55" width="118" height="70" rx="14" style="fill:var(--panel)"/><rect x="313" y="55" width="118" height="70" rx="14" fill="#059669" opacity=".14" stroke="#059669" stroke-width="2"/><circle cx="372" cy="55" r="13" fill="#059669"/><text x="372" y="60" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">3</text><text x="372" y="88" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">选 Skill</text><text x="372" y="104" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">或命令</text></g><g class="sat" style="animation-delay:0.4s"><rect x="469" y="55" width="118" height="70" rx="14" style="fill:var(--panel)"/><rect x="469" y="55" width="118" height="70" rx="14" fill="#d97706" opacity=".14" stroke="#d97706" stroke-width="2"/><circle cx="528" cy="55" r="13" fill="#d97706"/><text x="528" y="60" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">4</text><text x="528" y="96" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">动手干活</text></g><g class="sat" style="animation-delay:0.6s"><rect x="625" y="55" width="118" height="70" rx="14" style="fill:var(--panel)"/><rect x="625" y="55" width="118" height="70" rx="14" fill="#dc2626" opacity=".14" stroke="#dc2626" stroke-width="2"/><circle cx="684" cy="55" r="13" fill="#dc2626"/><text x="684" y="60" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">5</text><text x="684" y="96" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">权限把关</text></g><g class="sat" style="animation-delay:0.8s"><rect x="781" y="55" width="118" height="70" rx="14" style="fill:var(--panel)"/><rect x="781" y="55" width="118" height="70" rx="14" fill="#0891b2" opacity=".14" stroke="#0891b2" stroke-width="2"/><circle cx="840" cy="55" r="13" fill="#0891b2"/><text x="840" y="60" text-anchor="middle" font-size="13" font-weight="700" fill="#fff">6</text><text x="840" y="88" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">写回结果</text><text x="840" y="104" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">+ 记忆</text></g><path d="M840 125 C840 215 60 215 60 128" fill="none" stroke="#2563eb" stroke-width="3" stroke-dasharray="8 6" class="dashline"/><polygon points="60,128 53,142 67,140" fill="#2563eb"/><text x="450" y="232" text-anchor="middle" font-size="14" font-weight="600" fill="#2563eb">下一轮更懂你</text><circle r="7" fill="#f59e0b" class="runner"/></svg>
</div></body></html>

③ 怎么合作(小球绕圈)

你写 reqAI 整理成问题AI 做事并写 reply你确认 ✅归档下一轮

怎么动的

  1. 路线是圆:offset-path: circle(135px at 380px 190px)(半径 135,圆心 380,190),小球沿圆周跑,6 秒一圈。
  2. 虚线圆是同样的圆,用 <circle fill="none" stroke-dasharray="8 6"> 画,同样靠 stroke-dashoffset 动画流动。
  3. 5 个方块也是按角度放在一个椭圆上(横向放大 1.5 倍),和图 ① 同一个思路。
  4. 最后一行 @media (prefers-reduced-motion: reduce) 会在用户系统设置了"减少动态效果"时关掉所有动画——这是无障碍的通用做法,别删。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>③ 怎么合作(小球绕圈)</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.ovw h2{border-top:0;margin-top:8px}.ovw .card2{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;margin:14px 0}
.ovw h3{margin:0 0 6px}.ov{width:100%;height:auto;display:block;color:var(--text)}
.ov .core{animation:pulse 2.4s ease-in-out infinite;transform-origin:center;transform-box:fill-box}
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.07)}}
.ov .dashline{animation:dash 1.4s linear infinite}@keyframes dash{to{stroke-dashoffset:-24}}
.ov .sat{animation:pop .6s ease both;transform-box:fill-box;transform-origin:center}@keyframes pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}
.ov .sat:hover rect{opacity:.32}
.ov .runner{offset-path:path('M60 90 L840 90');offset-distance:0%;animation:run 5s linear infinite}@keyframes run{to{offset-distance:100%}}
.ov .orbit{offset-path:circle(135px at 380px 190px);animation:run 6s linear infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
@media(prefers-reduced-motion:reduce){.ov *,.can *{animation:none!important}.ov .runner,.ov .orbit{display:none}}
</style></head><body><div class="box">
<svg viewBox="0 0 760 380" class="ov" role="img" aria-label="③ 怎么和 AI 合作(req / reply)"><circle cx="380" cy="190" r="135" fill="none" stroke="#94a3b8" stroke-width="3" stroke-dasharray="8 6" class="dashline"/><circle r="8" fill="#f59e0b" class="orbit"/><g class="sat" style="animation-delay:0.0s"><rect x="305" y="27" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="305" y="27" width="150" height="56" rx="14" fill="#2563eb" opacity=".14" stroke="#2563eb" stroke-width="2"/><text x="380" y="57" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">你写 req</text></g><g class="sat" style="animation-delay:0.1s"><rect x="498" y="120" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="498" y="120" width="150" height="56" rx="14" fill="#7c3aed" opacity=".14" stroke="#7c3aed" stroke-width="2"/><text x="573" y="150" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">AI 整理成问题</text></g><g class="sat" style="animation-delay:0.3s"><rect x="424" y="271" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="424" y="271" width="150" height="56" rx="14" fill="#059669" opacity=".14" stroke="#059669" stroke-width="2"/><text x="499" y="293" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">AI 做事</text><text x="499" y="309" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">并写 reply</text></g><g class="sat" style="animation-delay:0.4s"><rect x="186" y="271" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="186" y="271" width="150" height="56" rx="14" fill="#d97706" opacity=".14" stroke="#d97706" stroke-width="2"/><text x="261" y="301" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">你确认 ✅</text></g><g class="sat" style="animation-delay:0.6s"><rect x="112" y="120" width="150" height="56" rx="14" style="fill:var(--panel)"/><rect x="112" y="120" width="150" height="56" rx="14" fill="#dc2626" opacity=".14" stroke="#dc2626" stroke-width="2"/><text x="187" y="142" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">归档</text><text x="187" y="158" text-anchor="middle" font-size="13" font-weight="600" fill="currentColor">下一轮</text></g></svg>
</div></body></html>

动效配方

流动的虚线

怎么动的

  1. stroke-dasharray 把线切成"画 8、空 6"的虚线;动画把 stroke-dashoffset 一路减小,虚线整体向前滑动。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>流动的虚线</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.flow{animation:flow 1s linear infinite}@keyframes flow{to{stroke-dashoffset:-14}}
</style></head><body><div class="box">
<svg viewBox="0 0 400 60" style="width:100%;max-width:420px"><line x1="10" y1="30" x2="390" y2="30" stroke="#2563eb" stroke-width="4" stroke-dasharray="8 6" class="flow"/></svg>
</div></body></html>

沿路径走的小球

怎么动的

  1. offset-path 指定路线,offset-distance 从 0% 到 100%。路线可以是任意 SVG 路径。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>沿路径走的小球</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.ball{offset-path:path("M20 90 C120 -10 280 -10 380 90");animation:go 3s ease-in-out infinite alternate}@keyframes go{from{offset-distance:0%}to{offset-distance:100%}}
</style></head><body><div class="box">
<svg viewBox="0 0 400 120" style="width:100%;max-width:420px"><path d="M20 90 C120 -10 280 -10 380 90" fill="none" stroke="#94a3b8" stroke-width="3" stroke-dasharray="6 6"/><circle r="9" fill="#f59e0b" class="ball"/></svg>
</div></body></html>

呼吸(脉冲)

呼吸

怎么动的

  1. 用 transform: scale() 在 1 和 1.08 之间来回;ease-in-out 让两端慢、中间快,像呼吸。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>呼吸(脉冲)</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.pulse{display:grid;place-items:center;width:120px;height:120px;border-radius:50%;background:#2563eb;color:#fff;font-weight:700;animation:pulse 2.4s ease-in-out infinite}@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.08)}}
</style></head><body><div class="box">
<div class="pulse">呼吸</div>
</div></body></html>

依次弹出

ABCD

怎么动的

  1. 每张卡片同一个动画,只是 animation-delay 不同(0、0.15、0.3 秒),就有了"一个接一个"的效果。both 让动画开始前保持透明。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>依次弹出</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.pops{display:flex;gap:10px}.pops span{display:grid;place-items:center;width:64px;height:64px;border-radius:14px;background:#7c3aed;color:#fff;font-weight:700;animation:pop .6s ease both}@keyframes pop{from{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}
</style></head><body><div class="box">
<div class="pops"><span style="animation-delay:0s">A</span><span style="animation-delay:.15s">B</span><span style="animation-delay:.3s">C</span><span style="animation-delay:.45s">D</span></div>
</div></body></html>

上下漂浮

🚀

怎么动的

  1. translateY 在 0 和 -8px 之间来回,3 秒一轮,适合图标、插画的"活起来"。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>上下漂浮</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.bob{font-size:3rem;display:inline-block;animation:bob 3s ease-in-out infinite}@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-8px)}}
</style></head><body><div class="box">
<div class="bob">🚀</div>
</div></body></html>

描边画出来(手写感)

怎么动的

  1. 先把 stroke-dasharray 设成整条线的长度,再把 stroke-dashoffset 从"整条长度"减到 0——线就像被笔一点点画出来。长度用 pathLength="1" 统一成 1,不用自己算。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>描边画出来(手写感)</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.draw{stroke-dasharray:1;stroke-dashoffset:1;animation:draw 2.5s ease forwards infinite}@keyframes draw{0%{stroke-dashoffset:1}70%,100%{stroke-dashoffset:0}}
</style></head><body><div class="box">
<svg viewBox="0 0 200 80" style="width:100%;max-width:260px"><path d="M10 60 C40 0 70 0 100 40 S160 80 190 20" fill="none" stroke="#059669" stroke-width="5" stroke-linecap="round" pathLength="1" class="draw"/></svg>
</div></body></html>

流光文字

动起来的标题

怎么动的

  1. 渐变背景比文字宽一倍(background-size:200%),再平移 background-position;background-clip:text 让渐变只显示在文字里。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>流光文字</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.shine{margin:0;font-size:2rem;background:linear-gradient(90deg,#2563eb,#db2777,#f59e0b,#2563eb);background-size:200%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:shine 4s linear infinite}@keyframes shine{to{background-position:200% 0}}
</style></head><body><div class="box">
<h2 class="shine">动起来的标题</h2>
</div></body></html>

加载转圈

怎么动的

  1. 一个有一侧彩色的圆环,rotate 0→360° 线性无限旋转。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>加载转圈</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.spin{width:48px;height:48px;border-radius:50%;border:5px solid #cbd5e1;border-top-color:#2563eb;animation:spin .9s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}
</style></head><body><div class="box">
<div class="spin"></div>
</div></body></html>

光标闪烁的打字效果

Hello, 你好!

怎么动的

  1. 宽度用 steps() 一格一格增加(不是平滑变宽),末尾的光标用 border-right 加闪烁动画。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>光标闪烁的打字效果</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.type{display:inline-block;overflow:hidden;white-space:nowrap;border-right:3px solid #14233a;font:700 1.5rem monospace;width:0;animation:typing 3s steps(10) infinite alternate,blink .7s step-end infinite}@keyframes typing{to{width:11ch}}@keyframes blink{50%{border-color:transparent}}
</style></head><body><div class="box">
<div class="type">Hello, 你好!</div>
</div></body></html>

悬停抬起 + 微旋转

把鼠标放上来

怎么动的

  1. 鼠标放上去时 transform 改变,配 transition 就有平滑过渡。这类"交互动效"不用 @keyframes。
源码(单文件 HTML,复制后保存成 .html 双击就能打开)
<!doctype html>
<html lang="zh"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>悬停抬起 + 微旋转</title>
<style>
:root{--panel:#fff;--line:#d0d7e2;--text:#14233a;--bg:#f4f7fb}
body{margin:0;padding:24px;background:var(--bg);color:var(--text);font-family:system-ui,"Microsoft YaHei",sans-serif}
.box{max-width:900px;margin:0 auto}
.lift{display:inline-block;padding:18px 24px;border-radius:14px;background:#fff;border:1px solid #d0d7e2;box-shadow:0 2px 6px rgba(0,0,0,.08);transition:transform .2s,box-shadow .2s}.lift:hover{transform:translateY(-6px) rotate(-2deg);box-shadow:0 12px 24px rgba(0,0,0,.15)}
</style></head><body><div class="box">
<div class="lift">把鼠标放上来</div>
</div></body></html>

关于 GIF / Flash / Lottie(如实说明)

  1. Flash 已经不能用了:Adobe 2020 年底停止支持,所有主流浏览器都已移除。想要同样效果,现在用的是 CSS 动画 + SVG(本页)或 Lottie(把设计师做的动画导出成 JSON,网页用小库播放)。
  2. GIF:好处是到处都能放(邮件、聊天),缺点是体积大、只有 256 色。本页的动画是实时绘制的,放大不糊、体积只有几 KB;要 GIF 需要另外"录屏转换",本页目前没有提供现成 GIF。
  3. Lottie:适合复杂的插画动画,需要用 After Effects 等工具做,本页暂时没有 Lottie 示例。
  4. 以上三项只做了"说明",没有假装已经做完。要不要补 GIF 导出或 Lottie,在 reply 里告诉 AI。

所有动画在系统开启"减少动态效果"时会自动停止。