懶人包
- animate 是 Emil Kowalski 開源在
emilkowalski/skills(MIT)裡的 Claude Code skill,2026-08-05 加入。它把「做一個動畫」拆成 7 步固定順序:先問該不該動、為了什麼,才輪到工具、屬性、曲線、中斷與退場。- repo 在 2026-10-21 是 48.2k stars、2.8k forks,這是 15 支 skill 共用的數字,不是 animate 一支的。
- 我用同一句需求「替帳號下拉選單和 Ctrl+K 命令面板加開關動畫」各跑多次:沒裝 skill 的 3 次全都替面板加了動畫,其中 1 次還把 Ctrl+K 弄成按了打不開;有 skill 的 4 次全部拒絕替 Ctrl+K 加動畫,理由是鍵盤快捷鍵一天會按上百次。
- 有 skill 的下拉選單統一用
scale(0.95)、cubic-bezier(0.23, 1, 0.32, 1),開 180ms、關 120ms(4 次裡 3 次如此);開了「減少動態效果」時保留淡入淡出,沒裝 skill 的版本則直接把動畫全關。- 沒點名的情況跑 3 次,3 次都自動載入;只打
/animate不帶需求,它只回一句固定開場白。在 Git Bash 用claude -p "/animate ..."時,/animate會被改寫成 Windows 路徑。
- animate skill 是什麼?
- 裡面有哪兩份檔案、各做什麼?
- 7 步決策在講什麼?
- 實測:同一句需求,有沒有 skill 差在哪
- 什麼時候會觸發?要不要點名?
- 怎麼安裝到 Claude Code?
- 限制與坑
- 適合誰、不適合誰?
- 延伸資源
🎬 animate skill 是什麼?
animate 是一份給 AI coding agent 讀的 SKILL.md,作者是 Emil Kowalski(toast 函式庫 Sonner 的作者),收在 emilkowalski/skills 這個 MIT 授權的 repo 裡。README 對它的介紹只有一句:從零做一個動畫,同時選對曲線、時長、屬性等細節。
它自稱是「construction skill」,只做一件事:把「幫我加個動畫」變成一段能通過嚴格審查的實作。審查既有動畫、掃整個專案、找哪裡可以加動畫、寫 React Native,都明確交給同 repo 的其他 skill(review-animations、improve-animations、find-animation-opportunities、animate-expo)。
它開宗明義列了兩種失敗,並說第一種比較糟:
- 替不該動的東西加了動畫。 所以第一步的關卡有時候會產出「零行程式碼」,skill 原文說這是成功,不是推託。
- 該動的東西用錯材料:進場用
ease-in、從scale(0)長出來、toast 用 keyframes、下拉選單的時長拖到讓人覺得卡。
📦 裡面有哪兩份檔案、各做什麼?
資料夾裡只有兩個檔案(以 commit 2d22863 為準):
| 檔案 | 行數 | 內容 |
|---|---|---|
SKILL.md | 207 | frontmatter、開場白規則、5 條硬規則、7 步決策流程、Never Ship 自檢表、輸出格式 |
RECIPES.md | 324 | 14 個常見元件的現成寫法 |
- 5 條硬規則:照順序走、不准用「看起來眼熟」的近似值(曲線、時長、spring 參數都要從表裡拿)、專案已經有
--ease-out之類的 token 就沿用不要另起一套、減少動態效果與 hover 防護要跟動畫一起交付、能用最便宜的工具就不要裝動畫函式庫。 - Never Ship 表:13 列「不准出貨」的寫法和替代做法,例如
transition: all、scale(0)進場、UI 用ease-in、沒理由超過 300ms、錨定在按鈕上的 popover 卻用transform-origin: center、動width/height/top/left、沒防護的:hover動畫、整群元素同時進場(要錯開 30–80ms)。原文說這 13 項每一項在review-animations裡都是直接擋下。
RECIPES.md 是 14 份食譜:按鈕按壓、下拉選單/popover、tooltip、modal、drawer、toast、手風琴、群組錯開進場、長按確認、分頁指示器、捲動揭示、拖曳關閉、用模糊遮掉不乾淨的交叉淡化、不靠函式庫的 WAAPI。每份都是一小段 CSS 或 JS 加一兩句「為什麼」,例如:
- tooltip 打開一個之後,鄰近的 tooltip 要瞬間出現(
transition-duration: 0ms),整排工具列才會感覺快。 - toast 刻意用
ease和 400ms,比一般 UI 慢,因為 Sonner 的手感是依元件個性調的。 - 長按確認的填色用
linear2 秒,放手時 200ms 收回,進度條本來就不該有緩動。 - 拖曳關閉除了距離門檻,還看速度(原文用
velocity > 0.11),並要求 pointer capture、多指防護、超出邊界的阻尼。
index.html,沒有一次打開 RECIPES.md。
🧭 7 步決策在講什麼?
這是整份 skill 的核心。原文要求按順序走,第 1、2 步沒過就不准往下。
第 1 步:這東西該動嗎?
用「一天會觸發幾次」分四級:
| 頻率 | 決定 |
|---|---|
| 一天 100 次以上(鍵盤快捷鍵、命令面板開關) | 不加動畫,到此為止 |
| 一天數十次(hover、列表上下移動) | 只能快到幾乎察覺不到,或乾脆不加 |
| 偶爾(modal、drawer、toast) | 標準動畫 |
| 很少或第一次(新手引導、成功、慶祝) | 才有「好玩」的額度 |
第 2 步:目的是什麼?
必須能用六個詞之一說出目的:回饋、空間一致性、狀態提示、避免突兀跳動、說明(限行銷頁與新手引導)、驚喜(只限第 1 步最少用的那一級)。說不出來就不做。另外,使用者正在讀或操作的資料,不能為了風格而移動。
第 3 步:挑最便宜的工具
由上往下,符合就停:CSS transition → CSS @starting-style(掛載時進場)→ CSS animation(頁面忙的時候仍要順,跑在主執行緒外)→ WAAPI(要程式控制但不想加函式庫)→ Motion(spring、版面動畫、退場、手勢)。
如果需求其實是「元件」而不是動畫,例如 toast、drawer、命令選單、下拉選單,要停下來改用 pick-ui-library 選元件庫,避免手刻出一個沒有焦點管理的 <div> 下拉選單。
第 4 步:動哪些屬性
- 只動
transform和opacity;clip-path是第四個許可項,height只限手風琴。 - 不准
scale(0),從scale(0.9–0.97)加opacity: 0開始。 - popover、下拉選單、tooltip 的
transform-origin放在觸發它的按鈕上;modal 例外,維持置中。 translate()優先用百分比;Motion 裡用完整的transform字串而不是x/y簡寫。- 不要用父層的 CSS 變數去驅動子元素的 transform,每個子元素都會重算樣式。
第 5 步:曲線、時長或 spring
曲線依情境挑:進場、退場用 ease-out;畫面上移動用 ease-in-out;hover 和顏色用 ease;等速運動用 linear。UI 一律不用 ease-in,因為它在使用者盯著看的那一刻最慢。
它認為 CSS 內建的曲線太弱,給了三個 token:
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
時長表:按鈕回饋 100–160ms、tooltip 125–200ms、下拉選單 150–250ms、modal 與 drawer 200–500ms,UI 動畫原則上 300ms 以內。拖曳、可中途反轉的手勢改用 spring,原文建議 { type: "spring", duration: 0.5, bounce: 0.2 },bounce 控制在 0.1–0.3。
第 6 步:被打斷與退場
會被連續觸發的東西用 transition 不用 keyframes,因為 transition 會從當下的值接著走,keyframes 會從頭重播。手勢用 spring 才能把速度帶過中斷點。怎麼進來就怎麼出去。使用者在做決定的地方用不對稱時間,例如長按確認按住時 2 秒、放開 200ms。
第 7 步:減少動態效果與 hover 防護
這兩項「每次都跟著動畫一起出貨」。prefers-reduced-motion 的意思是更少、更溫和,不是歸零:保留有助理解的淡入淡出,拿掉位移。hover 動畫要包在 @media (hover: hover) and (pointer: fine) 裡,避免觸控裝置點一下就觸發假 hover。
🧪 實測:同一句需求,有沒有 skill 差在哪
實驗設計
我在暫存目錄建了一個 75 行的 index.html:一個「帳號」下拉選單和一個 Ctrl+K 命令面板,兩者原本都用 display: none 瞬間切換。需求故意把兩個東西寫在一起,因為依照 skill 第 1 步,下拉選單屬於「偶爾」,命令面板屬於「一天 100 次以上」:
幫這個頁面(index.html)的「帳號」下拉選單和 Ctrl+K 命令面板加上開啟/關閉的動畫,讓介面感覺更精緻。直接修改 index.html,不要裝套件、不要用 CDN。改完就結束,最後用三五行說明你做了什麼。
每次都是全新目錄,用 headless 模式執行:
CLAUDE_CODE_DISABLE_CLAUDE_MDS=1 claude -p "$PROMPT" \
--setting-sources project --strict-mcp-config --model sonnet \
--dangerously-skip-permissions --output-format stream-json --verbose
--setting-sources project 加上關掉 CLAUDE.md,是為了不讓我自己的全域設定和 skill 混進來。環境是 Claude Code 2.1.306,模型是 Sonnet。分三組:
| 組別 | 設定 | 次數 |
|---|---|---|
| 沒有 skill | 專案裡沒有任何 skill | 3 |
| 有 skill、沒點名 | .claude/skills/animate/ 已裝,需求原樣送出 | 3 |
| 有 skill、點名 | 用 skills CLI 安裝,需求前面加 /animate | 1 |
結果
| 項目 | 沒有 skill(3 次) | 有 skill(4 次) |
|---|---|---|
| Ctrl+K 命令面板 | 3 次都加了 180ms 淡入加位移縮放 | 4 次都拒絕加動畫,維持瞬間開關 |
| 下拉選單起始狀態 | translateY(-4~-6px) scale(.96~.97) | scale(0.95),不位移 |
| 下拉選單時長 | 開關同為 150 或 160ms | 3 次開 180ms、關 120ms;1 次開關同為 150ms |
| 曲線 | 透明度用 ease;位移縮放 3 次各不同(cubic-bezier(.2,.8,.2,1)、cubic-bezier(.23,1,.32,1)、ease) | 4 次全用 cubic-bezier(0.23, 1, 0.32, 1),點名那次還定義成 --ease-out token |
| 減少動態效果 | 3 次都把動畫時間設成 0 或整個關掉 | 4 次都保留淡入淡出,只拿掉縮放 |
| 能不能用 | 1 次 Ctrl+K 按了打不開 | 4 次都能用 |
transform-origin 設在左上角、也就是按鈕的位置,都用 visibility 延遲讓關閉時也有動畫。差異集中在「該不該動」和「數值從哪來」。
有 skill 的 4 次在最後說明裡都給了拒絕的理由。沒點名的第 2 次是這樣寫的:
Ctrl+K 是鍵盤快捷鍵,一天可能按上百次,每次都等動畫會覺得拖慢。Raycast 這類工具也是刻意做成瞬間開關。如果你堅持要,我可以加一個約 100ms 只做淡入、不做位移的版本。
點名那次則多建議了一個替代方案:不做開關動畫,改加靜態的快捷鍵提示。這兩個說法都對得上 skill 第 1 步「直說並給非動畫替代方案」的要求。
逐格看下拉選單
我用 Playwright 開啟產出的頁面,觸發開啟後把 document.getAnimations() 全部暫停,再把時間軸設到指定毫秒截圖。上排是沒有 skill 的第 3 次,下排是有 skill、沒點名的第 2 次:
兩者總時長只差 20ms,差在前段。cubic-bezier(0.23, 1, 0.32, 1) 前段衝得很快,第 30ms 透明度已經 0.60,內建 ease 這時才 0.27。這就是 skill 說「內建曲線太弱」的意思:同樣不到 200ms,前 60ms 看到的東西不一樣多。
Ctrl+K 第 60ms
沒有 skill 的第 1 次還有一個實際的 bug:它把 .open 狀態從 display: flex 改成只調透明度和 visibility,卻留著基底樣式的 display: none。我用 Playwright 按 Ctrl+K 後量了 0 到 1000ms,class 確實變成 open,display 一直是 none,畫面上什麼都沒出現。那次的最後說明自己也寫了「沒有在瀏覽器裡實際開啟測試」。有 skill 的版本沒碰命令面板,自然沒有這個風險。
這組實驗不能證明什麼
- 每組只有 3 次(點名只有 1 次),而且只用 Sonnet 一個模型、一個頁面。
- 「拒絕替 Ctrl+K 加動畫」對不對,取決於你是否同意 skill 的立場。如果需求方明確要求面板有動畫,skill 的做法會變成多一輪溝通。
- 沒有 skill 的第 2 次湊巧也用了
cubic-bezier(.23,1,.32,1),可見模型本來就認得這條曲線,skill 的作用是讓它每次都用、而且用在每個屬性上。 - 時長和手感我只量了數值,沒有做使用者測試。
🚦 什麼時候會觸發?要不要點名?
frontmatter 的 description 列了觸發情境:被要求替某個東西加動畫、加 motion、讓元件「活起來」、做 transition。它也寫明「批評既有動畫用 review-animations,稽核整個專案用 improve-animations」,等於告訴模型這三種需求各走哪條路。
animate 沒有設 disable-model-invocation,模型可以自己決定載入。同 repo 只有 pick-ui-library、prototype、review-animations 三支設了這個欄位,那三支一定要手動點名。
實測結果:
- 沒點名:3 次都在第一步呼叫了 Skill 工具載入
animate。這和 apple-design 那篇 的結果不同,那支 skill 在類似條件下 3 次只觸發 1 次。我的推測是「加動畫」這個字面需求和 animate 的 description 幾乎逐字對上,但只有 3 次樣本,不能當成保證。 - 點名:在需求前面加
/animate,skill 內容直接注入,不會出現 Skill 工具呼叫,產出同樣遵守 7 步。 - 只打
/animate不帶需求:只回一句固定開場白 "I'm ready to build animations that feel right, my knowledge comes from Emil Kowalski's animation philosophy.",然後等你下指令。這是 2026-09-15 加進 SKILL.md 的 Initial Response 規則,當天另一個 commit 拿掉了句尾的課程連結。
⚙️ 怎麼安裝到 Claude Code?
先確認 CLI 存在,npx skills@latest --help 會列出 add、list、remove、update 等指令(我執行時抓到的是 1.7.4)。只裝 animate 一支:
npx skills@latest add emilkowalski/skills --skill animate
不想回答互動問題,就指定 agent 並加上 -y。我在空目錄實跑的是這行:
npx -y skills@latest add emilkowalski/skills --skill animate --agent claude-code --copy -y
結果:
- 產生
.claude/skills/animate/SKILL.md與RECIPES.md,和 repo 原檔diff -r比對完全相同。 - 根目錄多一個
skills-lock.json,記錄來源emilkowalski/skills與檔案雜湊。 - 安裝過程顯示安全評估:Gen「Safe」、Socket「0 alerts」、Snyk「Low Risk」。
--copy 是複製檔案而不是建 symlink,在 Windows 上比較單純。要裝到使用者層級(所有專案共用)就加 -g。
🕳️ 限制與坑
- Git Bash 會吃掉
/animate:我第一次在 Git Bash 跑claude -p "/animate",模型收到的是C:/Program Files/Git/animate,因為 MSYS 把開頭的/當成路徑轉換了。模型自己認出問題並反問要做什麼動畫。加上MSYS_NO_PATHCONV=1重跑,就正確回出開場白。在互動式 Claude Code 裡打/animate不受影響,這只發生在從 Git Bash 傳參數給claude -p的時候。 - 它會說「不」:第 1 步是硬規則。如果你的產品就是要命令面板有開場動畫,要在需求裡講清楚,或是改請它做「約 100ms 只淡入」的折衷版,它自己也提過這個選項。
- RECIPES.md 不一定會被讀:4 次實測都沒打開。下拉選單的食譜是 200ms,實測產出是 150 或 180ms,都在 SKILL.md 時長表的 150–250ms 內,但不是食譜原值。想要它照食譜做,就在需求裡直接說「照 RECIPES.md 的 dropdown」。
- 手感它判斷不了:skill 自己規定要在說明裡指出哪裡要靠眼睛確認,4 次實測都建議用 DevTools 的動畫面板放慢播放。它給的數值是起點,不是驗收。
- 元件需求會轉給別支 skill:toast、drawer、命令選單這類從零開始的元件,skill 要求先用 pick-ui-library 選元件庫。只裝 animate 一支時,這個轉介會落空。
🙋 適合誰、不適合誰?
適合:
- 寫網頁前端、常請 AI 加 hover、下拉、modal 動畫,想讓數值有一致來源的人。
- 專案已有 design token,希望 AI 沿用
--ease-out這類變數而不是每次自創一條曲線。 - 想要減少動態效果與觸控 hover 防護「預設就有」,不用每次提醒。
- 審查或重構既有動畫:animate 只負責從零做。審一段既有動畫看 review-animations,掃整個專案用 improve-animations。
- React Native/Expo:skill 明說交給 animate-expo。
- 原生 iOS、Android:範例全是 CSS、WAAPI 與 Motion。
- 行銷頁、需要大量表演性動畫:它的時長表和「100 次」關卡是為產品 UI 設計的,行銷頁可以更長,但它的預設會讓你收斂。
🔗 延伸資源
- GitHub repo:emilkowalski/skills
- skill 原文:skills/animate/SKILL.md、RECIPES.md
- 同作者的手勢與物理動效:apple-design skill 實測
- 第 3 步會轉介的元件庫挑選:pick-ui-library
- 同一把尺的審查版:review-animations
display: none 切換的下拉選單和一個鍵盤快捷鍵觸發的面板,用 /animate 請 Claude Code 一起處理,看它對兩者的判斷是否和你預期一致,再用 DevTools 動畫面板放慢 4 倍看前 60ms。