设计稿 → 生产代码
令牌与设计稿冲突时,谁赢
这是还原工作里最容易含糊、也最容易扯皮的一条。分维度定优先级,不要笼统地喊「1:1 还原」:
| 维度 | 谁赢 | 说明 |
|---|---|---|
| 颜色 | 项目令牌 | 设计稿的十六进制映射到令牌;如果令牌里没有对应值,报出来新增,不要硬编码 |
| 字体族 | 项目令牌 | 设计稿用的字体没授权就换,并明确告知 |
| 字号 / 间距尺度 | 项目令牌,差异需上报 | 设计稿 13px 而尺度里只有 12/16 → 报给设计师,不要静默取整 |
| 布局几何(位置、对齐、结构) | 设计稿 | 这是设计的本体,不要按自己的审美改 |
| 圆角 | 设计稿 | 除非项目有强制的形状语言(例如全站只允许 0px) |
| 交互状态 | 项目规范 | 设计稿通常没给,按第三节补齐 |
| 组件边界 | 项目既有组件 | 设计稿画成一个整块,但项目里已有能拼出的组件 → 复用 |
一句话:颜色和尺度听代码库,布局几何听设计稿,两者的差值记进验收报告。
总原则:设计稿给的是「长什么样」,项目给的是「怎么组织」。前者服从设计稿,后者服从代码库。
最常见的失败是两件事同时发生:模型把 MCP 生成的 React + Tailwind 直接粘进一个 Vue + CSS Modules 的项目,同时凭记忆目测间距。结果是既不还原、也不符合项目约定。
一、取数顺序(不许跳步)
| 步 | 动作 | 为什么 |
|---|---|---|
| 1 | 确认节点。 从链接里取 fileKey 与 node-id(形如 node-id=1-2)。桌面端可直接选中图层。 | 节点错了后面全错 |
| 2 | get_design_context | 拿到结构化设计数据 + 默认代码。这是主数据源 |
| 3 | 响应过大或被截断 → get_metadata | 拿到稀疏的图层树(id / 名称 / 类型 / 位置 / 尺寸),再只对需要的子节点重取 get_design_context |
| 4 | get_variable_defs | 拿到设计变量(颜色 / 间距 / 字体),用于映射到项目令牌。这一步最常被跳过,也是「看起来像但不对」的根因 |
| 5 | get_screenshot | 视觉基准。必须拿到,否则无法验收 |
| 6 | get_code_connect_map(若有 Code Connect) | 拿到「Figma 节点 → 项目组件」的映射,优先复用既有组件而不是重造 |
| 7 | 下载/导出资源 | 图标导出为 SVG,图片按 @2x 或按实际显示尺寸 |
| 8 | 写代码 | 翻译成项目约定(见第二节) |
| 9 | 1:1 验收 | 截图对比 + 尺寸核对(见第四节) |
前置检查:如果 MCP 无响应,先确认连接(见 references/figma-mcp-setup.md),不要靠「照着截图猜」硬做——猜出来的偏差会全部变成返工。
远程 vs 桌面
- 远程服务器:基于链接。复制 frame / layer 的链接给 MCP,客户端从链接里解析 node id(它不会去浏览页面)。
- 桌面(Dev Mode):基于选中。可以直接选中图层提问,不需要链接。
二、翻译成项目约定(这一步才叫「实现」)
MCP 吐出来的默认代码是参考,不是成品。逐项翻译:
| MCP 输出 | 你要做的 |
|---|---|
| React + Tailwind | 转成项目框架(Vue / Svelte / SwiftUI / 原生 HTML+CSS…) |
| Figma 变量名 | 映射到项目令牌。找不到对应令牌就新增,不要硬编码十六进制 |
| 绝对定位的图层 | 改成正常文档流 / Flex / Grid。设计稿的绝对坐标是实现细节,不是布局方案 |
| 内联样式 | 抽成 class / 组件 props |
| 硬编码文案 | 抽成 i18n key 或 props |
| 单个大块 JSX | 按设计稿的图层结构拆成组件 |
| 哑组件 | 补齐 props、状态、事件(设计稿通常只有静态态) |
| 默认间距值 | 对齐项目的间距尺度;如果设计稿的值不在尺度里,先跟设计师确认,不要自己改 |
令牌映射表(写代码前先填)
设计变量 → 项目令牌 color/bg/primary → --color-surface-1 color/text/default → --color-text-primary spacing/4 → --space-4 radius/md → --radius-md text/heading-lg → --step-3
发现设计变量和项目令牌对不上时,报出来。 「设计稿用了 13px 的间距,项目尺度里没有 13」是有价值的信息,不是要你偷偷取整。
复用优先
- 项目里已经有对应组件 → 复用,不要新建。
- 差一点点 → 加一个 variant / prop,不要 fork 出第二份。
- 确实没有 → 新建,放在项目既有的组件目录里,命名跟随既有风格。
三、还原精度
设计稿里必须严格对齐的:
- 字号、字重、行高、字距
- 颜色(用令牌,不用吸管取色)
- 间距(内边距、元素间距)
- 圆角
- 图标尺寸与线宽
- 元素对齐关系
设计稿里允许你自己决定的(这些是设计稿的空白,不是遗漏):
- 悬停 / 聚焦 / 按下 / 禁用状态(除非稿里有)
- 空状态、加载态、错误态
- 响应式行为(设计稿通常只给了 1–2 个宽度)
- 长文本溢出策略
- 键盘操作与焦点顺序
- 动画曲线与时长
遇到设计稿明显不合理的地方(对比度不足、点击区 < 44px、12px 正文、色盲不可辨的状态色):实现符合规范的那一版,并明确告诉用户你偏离了哪里、为什么。 不要沉默地照抄,也不要沉默地改掉。
四、1:1 验收(不跑这一步等于没做)
1. 在相同宽度下截图(设计稿导出 + 实际渲染),宽度必须一致,否则一切对比无意义 2. 叠图对比(50% 透明度)或用像素 diff 3. 逐项量:边距、字号、行高、色值 4. 只看差异 > 2px 或色差 ΔE > 2 的位置 5. 修正后重新截图,直到差异只剩抗锯齿
推荐同时看三个宽度:1440 / 1024 / 390。设计稿通常只给一个,另外两个是你补的,要确认补得合理而不是硬挤。
用 Playwright 量而不是用眼睛估
python# 逐个关键元素读实际盒模型,跟设计稿数值对照 page.set_viewport_size({"width": 1440, "height": 900}) el = page.query_selector(".hero-title") box = el.bounding_box() computed = page.evaluate("""el => { const s = getComputedStyle(el); return { fontSize: s.fontSize, lineHeight: s.lineHeight, letterSpacing: s.letterSpacing, color: s.color, fontFamily: s.fontFamily }; }""", el) print(box, computed)
不要凭截图目测间距。 目测的误差是 4–8px,肉眼看不出来但并排一看就歪。
验收报告
## 还原验收 | 项 | 设计稿 | 实现 | 差异 | 处理 | |---|---|---|---|---| | 标题字号 | 48px | 48px | 0 | — | | 标题字距 | -1.44px | 0 | 1.44px | 已补 letter-spacing: -0.03em | | 卡片内边距 | 24px | 32px | 8px | 项目 --space-6=32,已与设计师确认采用 32 | 宽度:1440 / 1024 / 390 未验收:iframe 内滚动行为、Safari 下的字体回退
五、常见偏差与原因
| 症状 | 根因 | 修法 |
|---|---|---|
| 整体「像但不对」 | 只取了 get_design_context,没取 get_variable_defs | 补取变量并映射令牌 |
| 字体不对 | 设计稿用的字体项目没有 | 报出来,或找最接近的授权替代并说明 |
| 间距有 1–3px 偏差 | 设计稿用了非尺度值 | 与设计师确认,不要静默取整 |
| 大屏正常小屏崩 | 用绝对定位还原 | 改成 Flex/Grid + 流体尺寸 |
| 颜色在不同屏幕不一致 | 用了 sRGB 十六进制但设计稿是 P3 | 用 color(display-p3 …) 或统一色彩空间 |
| 图标糊 | 导出了 PNG 或尺寸不对 | 导出 SVG,或按 @2x/@3x 导出位图 |
| 悬停/聚焦完全没有 | 设计稿没给,就真没做 | 状态必须补(见第三节) |
| 点不动、键盘不可用 | 用 div 拼的交互元素 | 用语义元素;必要时补 role / tabindex / 键盘处理 |
六、自检
- 取数顺序走完,
get_variable_defs和get_screenshot都拿到了吗? - 令牌映射表填了吗?有没有残留硬编码色值?
- 复用了项目既有组件吗?还是又造了一份?
- 交付的是项目框架的代码,还是 MCP 默认的 React+Tailwind?
- 状态补齐了吗(hover / focus-visible / disabled / loading / empty / error)?
- 三个宽度都看过了吗?
- 验收报告里的每一项都有实际读到的数值支撑吗?
- 偏离设计稿的地方,有没有明确告知用户?


