给 AI 编码工具装上审美:Emil Kowalski 把设计师手感做成了 Skills
你让 Cursor 写一个下拉菜单,它八成会给你一个「弹」出来的。
从一个点「啵」地蹦到全尺寸,还带个回弹,像里面装了弹簧。第一次看你可能还觉得挺灵动,等到界面上第五个组件全这么弹,你就开始头疼了。整个页面像个跳跳床。
这是我这半年用编码 agent 写前端最直观的一个感受。模型能把功能写对,按钮能点,接口能通,状态能存下来。可只要一沾上动效,立马露馅。它不知道一个东西到底该不该动、该动多快、从哪个方向进来、出去的时候要不要跟进来对称。它脑子里好像只有一句话,加了动画看起来更高级,于是往死里加。
好家伙,这就是动效版的 AI 味。
前几天在 X 上刷到宝玉转的一条,Emil Kowalski 干了件挺有意思的事,他把自己这些年攒的一整套 UI 和动画的判断,做成了三个可以直接喂给 AI 的 Skill。所谓 Skill,就是 Claude Code、Cursor、Codex 这些编码 agent 现在都支持的一种能力包,本质是几个写满规则和参考值的 markdown 文件,你把它放进项目,agent 写代码前会先读一遍,照着里面的标准来。你可以理解成给模型塞了一本随身携带的作业本。
Emil 塞进去的这本作业本,讲的是审美。
说到这我得先介绍下这人,不然你可能没概念。Emil Kowalski 在 Vercel 和 Linear 都待过,这俩公司做的东西什么调性大家心里有数,是那种你一眼就知道「哦,很贵」的克制精致。更关键的是他手里有两个前端圈子里几乎人人用过的组件,一个叫 Sonner(github.com/emilkowalski/sonner),就是那个从屏幕角落优雅滑出来的消息提示 toast,另一个叫 Vaul(github.com/emilkowalski/vaul),移动端从底部拉上来的那种抽屉。他还开了门课专门讲网页动画,叫 animations.dev。
换句话讲,这不是某个营销号总结的「10 个动画技巧」,是一个真拿这个吃饭、作品被几十万人用过的人,把脑子里那套说不清道不明的手感,硬生生翻译成了机器能读的规则。这套东西现在全部开源在 github.com/emilkowalski/skills,配套还有个页面 emilkowal.ski/skill。
我把它扒下来读了一遍,越读越上头。因为它戳中的,恰恰是我平时最头疼的那件事。
先说这三个 Skill 是怎么分工的,设计得挺巧。
第一个叫 emil-design-eng,是主脑,管的是决策框架。它不教你怎么写代码,它教 agent 怎么判断「这个动画到底该不该存在」。第二个叫 review-animations,是质检员,你写完的动效代码丢给它,它拿一套很严的标准逐条审,输出一张 Before / After / Why 的表格,告诉你哪里不对、改成什么、为什么。第三个最有意思,叫 animation-vocabulary,是个翻译官,专门解决「你想要的效果说不出名字」这个千古难题。
顺着这个思路往下聊,你会发现它们其实对应了做一件事的三个阶段,动手前先想清楚要不要做、做完了自己审一遍、以及全程你得能准确说出你想要什么。这个结构本身就很有工程味,我看到的时候愣是笑了一下,这不就是把一个资深设计工程师脑子里的工作流,拆成了三个可以单独调用的模块么。

好,铺垫完了,来看真正的干货,也就是 Emil 到底往里塞了什么判断。
最核心的一条,也是整套东西的地基,就一句话,动画不是「让它动起来」,而是「让它感觉对」。
听着有点玄对吧,我用大白话展开一下。Emil 说每一条动画都必须能回答一个问题,它为什么要动。这个问题问得特别狠,因为它直接把 90% 的花哨动效判了死刑。
什么是合理的理由?比如空间一致性,你的消息提示从右上角滑进来,那它消失的时候也得从右上角滑出去,不能凭空蒸发,因为用户脑子里给它标了个位置。比如状态反馈,你按下一个按钮,它轻微缩小一点点,这是在告诉你的手指「我收到了」。比如防止突兀,一个元素直接啪地出现太吓人,让它淡入一下,用户的眼睛能跟得上。
什么是不合理的理由?「看起来很酷」。就这一条。如果一个动画唯一的作用是看起来很酷,而且它还高频出现,那它就该被删掉。
我第一次读到这我是真的服气。因为 AI 生成的动效,几乎全都栽在这一条上。模型没有「这个动作值不值」的概念,它只有「加上去更炫」的冲动。你不给它立个规矩,它就把每个 hover、每次点击、每个状态切换都塞满弹跳和渐变,最后就是那个跳跳床。
第二条我觉得是全套里最反常识、也最值钱的一条,按使用频率决定动画强度。
Emil 给了个特别清楚的分级。一天要用 100 次以上的操作,比如键盘快捷键、命令面板,禁止动画,一点都不要有。一天用几十次的,比如 hover、列表里上下导航,删掉或者大幅简化。偶尔用一次的,比如弹窗、抽屉、消息提示,可以上标准动画。极少用甚至只用一次的,比如新手引导、提交成功那一下,反而可以做点小惊喜。
这个逻辑一旦想明白,你会有点后背发凉的通透感。动画的成本不是一次性的,是乘以频率的。一个 200 毫秒的开场动画,你一天看两次,觉得高级。你一天看两百次,它就是两百次「等它演完我才能干活」的延迟。频率越高的地方,动画越是负担而不是加分。
我为什么对这条特别敏感,多说一句。我平时的活儿是给大模型搭那层让它真正能干活的工程脚手架,说人话就是管 agent 的工具链、调度、超时这些。这行干久了会形成一种条件反射,任何东西一旦进入高频路径,你对它的延迟容忍度就断崖式下跌。一个函数调用一天跑几次,慢个几十毫秒无所谓,一天跑几百万次,那几十毫秒就是要命的账单。Emil 这套按频率给动画分级的思路,跟我们优化高频代码路径的直觉,底层是一模一样的。原来审美和性能,在「尊重高频」这件事上,是同一件事。
再往下就是硬技术了,Emil 给了一堆具体到能直接抄的数值和规则,我挑几个最容易踩坑的说。
先说 easing,就是动画的快慢节奏曲线,一个动作是先快后慢还是匀速,全看它。Emil 的态度很干脆,别信浏览器默认的那条,太肉。他给了张对照表,元素进场退场用 ease-out(开头快结尾慢,干脆利落),已经在屏幕上的元素挪位置用 ease-in-out(两头都缓,稳),hover 和变色用 ease,匀速运动才用 linear。然后画了条红线,UI 动画绝对禁止用 ease-in,因为 ease-in 是开头慢,用户会实实在在地感觉到一顿卡。
再说时长。Emil 说 UI 动画基本都得压在 300 毫秒以内,超过就开始拖沓。他给的细分是,按钮按下的反馈 100 到 160 毫秒,小提示框 125 到 200,下拉选择器 150 到 250,大一点的模态框和抽屉 200 到 500。你别小看这几个数字,多数 AI 写出来的动画一上来就是 500 毫秒起步甚至更长,慢得像放幻灯片,问题就出在没有这个量级感。
然后是一条我觉得特别妙的,物理正确性。Emil 说永远不要从 scale(0) 开始,因为现实世界里没有东西是从「不存在」凭空长出来的。要做出现的效果,用 scale(0.95) 加透明度从 0 淡入,让它像本来就在那、只是刚被你看见。就这一个 0.95 和 0 的区别,前者是自然,后者就是文章开头那个跳跳床。他还有一条,弹出层要从触发它的那个按钮的位置缩放出来,而不是从元素自己的中心,这样用户的视线才有个来处,知道这东西是从哪冒出来的。
性能这块他也没含糊。只动 transform 和 opacity 这俩,因为它们能交给 GPU 单独渲染,不拖累主线程,别去动 width、height、margin 这些,一动就触发整个页面重新计算布局,卡。他甚至点名了 Framer Motion 这个流行动画库的一个坑,它那个 x、y、scale 的简写其实不走硬件加速,得老老实实写完整的 transform 字符串才行。这种细节,不是天天写动画写到手抽筋的人,根本抠不出来。
无障碍那条也值得说。系统里有个设置叫 prefers-reduced-motion,用户勾了它就是明确告诉你我晕动画。很多人的处理是一刀切全关掉,Emil 说这是偷懒,正确做法是保留淡入淡出和颜色变化,只把那些位移、缩放、弹跳给去掉。因为有些人晕的是「东西在动」,不是「东西在变」。这个分寸感,我觉得就是专业和业余的分水岭。
写到这我停下来想了想,你可能会问,这些规则我自己收藏一份不就完了,为啥非要做成给 AI 读的 Skill。
这就是我觉得这件事最有嚼头的地方了。
我们过去总有个默认假设,审美是人的护城河,是那种只可意会的东西,AI 学不会。可 Emil 干的这件事,恰恰是在证明,所谓审美,很大一部分其实是可以被结构化、被写下来、被检索的隐性知识。它不是玄学,它是一堆有前因后果的判断,只是从来没人耐心把它一条条码出来过。
你看那个 review-animations,它设了十条不可妥协的标准,还把审查结果的格式都焊死了。比如它会揪出 transition: all 300ms 这种写法,改成 transition: transform 200ms ease-out,理由是别用 all,那会把一堆不该动的属性也拖进动画拖垮性能。再比如揪出 transform: scale(0),改成 scale(0.95) 加 opacity: 0,理由就是前面说的不该凭空出现。你发现没,每一条改动后面都跟着一个 why。这个 why 才是真正的资产,它把「我觉得这样不好看」这种模糊的手感,翻译成了「因为它违反了物理直觉所以用户会觉得别扭」这种可以传递、可以复用的判断。
我干的这行,天天琢磨的就是怎么把知识喂给模型让它在对的时刻用对。看到 Emil 这套东西的时候,我有种同行相见的感觉。他不是在跟 AI 抢饭碗,他是把自己最贵的那部分经验,做成了一个可以无限复制的模具。以后一万个不懂动效的程序员用 Cursor 写界面,只要挂上这个 Skill,写出来的东西都自动带上了 Emil 的判断底线。厉害了,这个杠杆,比他自己再做十个组件都大。

最后那个 animation-vocabulary,看着最小,我却觉得它藏着另一层东西。
它就是个动效术语的反查词典。你说不出那个专业词,只能描述感觉,它帮你翻译。你说「iOS 划到底部会回弹那种感觉」,它告诉你那叫 Rubber-banding。你说「元素像是从按钮里长出来的」,它告诉你那叫 Origin-aware animation,起点感知动画。你说「那个啵一下弹进来的」,它告诉你那是 Pop in。
这玩意儿看着不起眼,但它解决的是个特别真实的痛点,人和 AI 之间的沟通带宽。你想要的效果越模糊,AI 猜得越离谱,最后就是来回改十遍还是不对。而当你能准确说出 Rubber-banding 的时候,你跟模型之间那层毛玻璃一下就擦干净了。它不光是让设计师和工程师之间不再鸡同鸭讲,更是让你能给 AI 下一个精准到不会被误解的指令。
我越来越觉得,未来会用 AI 和不会用 AI 的人,差距可能就差在这种词汇量上。不是编程的词汇,是描述你到底想要什么的词汇。你脑子里的画面越清晰、越有专业术语能对应,AI 就越是你手里那支笔。你只会说「弄得好看点」,那它给你的永远是跳跳床。
绕了一圈,还是回到开头那个蹦蹦跳跳的下拉菜单。
以前我遇到这种,只能自己一点点去调,把 scale(0) 改成 0.95,把 500 毫秒压到 200,把 ease-in 换掉。烦,而且下次换个项目又得从头来。现在我大概知道该怎么办了,把 Emil 这套 Skill 挂上,让 agent 自己先过一遍那些标准,我再拿 review 那个来审一道。相当于给我的编码 agent 请了个免费的、永远在线的设计工程师顾问。
我一直觉得,好的工具从来不是替你做决定,而是帮你把那些说不清的直觉,变成能反复用的东西。Emil 这次做的,就是把「感觉对」这三个字,拆开揉碎,码成了机器能懂的语言。
万青有句词我很喜欢,是谁来自山川湖海,却囿于昼夜厨房与爱。技术这行也一样,我们天天追着最新的模型、最炸的参数,可到最后能留下来、能被一遍遍复用的,往往是这种朴素得近乎笨拙的东西,一条一条把手感写清楚。
审美这件事,原来真的可以传下去。哪怕是传给一台机器。