Figma → 落地页 (HTML/CSS/JS)
该技能将 Figma 中的落地页设计转换为静态 HTML、CSS 和 JS 代码。 工作方式是逐块进行:每完成一个区块,代理都会暂停并等待用户确认。
布局规则(结构、BEM 命名法、单位、图像、悬停效果等)位于该技能的 templates/AGENTS.md 文件中。在第 3 步,该文件会被复制到项目根目录,并始终生效。
要求
- 已连接 Figma MCP(
get_metadata、get_design_context、get_screenshot,如有则get_variable_defs)。如果未连接,需告知用户并停止操作。 - 用户需提供类似
https://www.figma.com/design/:fileKey/:fileName?node-id=1-2的链接。 - 运行服务器、截屏和转换 WebP 需要 Node.js。首次运行
npx命令时会从网络下载包——Codex 可能会请求权限,这是正常的。
工作流程
按顺序执行以下步骤,不得跳过。
第 1 步:解析链接
fileKey——/design/之后的部分。如果链接中包含/branch/:branchKey/,则使用branchKey。nodeId——node-id的值,将连字符替换为冒号(1-2→1:2)。- 链接可能指向整个文档、页面、桌面框架或移动框架。类型将在第 2 步确定。
第 2 步:布局结构图
- 对链接中的节点调用
get_metadata(对于整个文档,不传node-id或传入根页面)。 - 找到落地页的框架版本:桌面版、移动版,有时还有平板版。从布局中确定宽度,不要使用默认值。同时找到页面上可能单独存在的模态窗口(弹出框)和打开的移动菜单框架。
- 在每个框架内,识别顶层的区块(页眉、英雄区、优势、评价、页脚等)。
- 在各版本之间匹配区块:「桌面区块 ↔ 移动区块」(根据图层名称、顺序和内容)。
- 向用户展示结构图并等待确认:
宽度:桌面 1440,移动 375
1. header — 12:30 ↔ 40:2
2. hero — 12:45 ↔ 40:18
3. advantages — 13:10 ↔ 41:5
...
模态窗口 / 菜单:
- mobile-menu — 45:12
- popup-order — 46:01
如果没有移动版,需告知用户并询问如何处理。
第 3 步:项目骨架和基础 UI
- 如果项目根目录中没有
AGENTS.md,则从技能文件夹复制templates/AGENTS.md。根据第 2 步的数据填写其中的「此落地页」部分(宽度、容器、字体)。断点保留默认值;仅当此布局在其他宽度下出现问题时才进行修改,并记录新的断点。 - 创建目录结构:
index.html、style.css、script.js、assets/icons/。 index.html:<!doctype html>、lang="ru"、charset、viewport、<title>和<meta name="description">根据落地页内容填写。不添加 favicon。script.js使用defer属性引入。- 字体:从
get_design_context/get_variable_defs中获取,仅通过 Google Fonts 引入所需的字重,使用display=swap。如果字体不在 Google Fonts 中,则向用户请求字体文件,通过assets/fonts/下的@font-face引入。 style.css:样式重置(参见AGENTS.md),然后是:root,包含颜色、字体、间距、容器宽度的变量。如果布局中有变量,则从get_variable_defs中取值;否则从布局中提取并取整。- 基础组件:将布局中通用的元素(按钮、区块标题、输入框)提取为可复用的类(
.btn、.section-title、.input、.container)。如果布局中没有包含状态(hover、focus、active)的 UI 组件库,仅一次询问用户整个项目中对通用按钮和链接的悬停规则。将回答记录到AGENTS.md的「此落地页」部分中的「UI 状态」一行。 - 工具(仅一次):
- 在后台从项目根目录启动本地服务器:
npx -y serve -l 3000(备选方案:python3 -m http.server 3000)。所有截图都从http://localhost:3000获取,而非file://; - 检查截图工具:如果已连接 Playwright MCP,则使用它;否则使用
scripts/shot.cjs脚本(参见「自我检查」); - 检查图像转换器(参见「图像」)并记录结果。
- 在后台从项目根目录启动本地服务器:
- 通知用户骨架已就绪,然后转到第一个区块。
第 4 步:逐块构建
对于结构图中的每个区块,严格从上到下按顺序进行(包括包含表单的区块):
- 数据。 获取桌面区块及其移动版配对区块的
get_design_context和get_screenshot。- 如果响应被截断或过大,则对该区块调用
get_metadata,并逐个获取其子节点。 - 响应中的代码(通常是 React + Tailwind)仅作为尺寸、颜色和结构的参考。不要复制其样式。
- 如果响应被截断或过大,则对该区块调用
- 图像。 下载并处理该区块的资源(参见「图像」)。
- 布局。 在
index.html中编写该区块的 HTML,在style.css中通过带注释的部分编写样式(例如/* ===== hero ===== */),在script.js中编写 JS(如果需要)。使用第 3.6 步中的基础类,不要复制按钮和标题的代码。先编写桌面版,然后通过clamp()和媒体查询实现响应式布局,直至移动版。- 对于移动宽度的
header,立即构建汉堡菜单(根据结构图中的框架或询问用户的具体样式)。 - 如果区块包含表单,请使用基本的浏览器验证属性(
required、type="email"、type="tel"、pattern)进行布局,但不要包含 JS 提交逻辑。
- 对于移动宽度的
- 自我检查。 在桌面、移动和中间宽度(1024、768)下仅截取当前区块的截图。与 Figma 截图进行比较:边距、尺寸、字体、颜色、换行。修正发现的问题并重新截图。
- 使用 Playwright MCP:在每个宽度下截取区块元素的屏幕截图。
- 没有 MCP 时,使用技能文件夹中的脚本:
脚本将截图保存为# 仅一次 mkdir -p .screens && cp <skill-folder>/scripts/shot.cjs .screens/ npm i playwright --prefix .screens && npx -y playwright install chromium # 每个区块之后 node .screens/shot.cjs http://localhost:3000 .hero 1440,1024,768,375.screens/<section>-<width>.png,并在页面超出屏幕宽度时输出⚠ 水平滚动警告。出现任何此类警告——请修复原因(不要在body上使用overflow: hidden来隐藏)。 - 区块确认后删除区块截图;脚本和
.screens/中的node_modules保留到第 6 步。
- 报告与暂停。 简要告知用户已完成内容、与布局的偏差及原因、需要为区块中独特的交互元素(如非标准卡片悬停效果、滑块参数)澄清的内容。等待确认。 将用户的修改应用到此区块,然后再次等待。
- 仅在收到「确认」后,再进入下一个区块。
第 5 步:模态窗口和表单逻辑
在所有主要区块布局完成后:
- 如果在第 2 步中发现了隐藏的模态窗口(弹出框),则构建它们,并实现打开/关闭触发器(按钮、
Esc键、点击遮罩层)。行为遵循AGENTS.md中的「JavaScript」部分。 - 每个窗口作为一个独立区块: 在打开状态下进行截图自检、报告并等待确认。
- 检查页面上所有表单的功能。在用户明确请求并提供 API 地址或技术任务说明之前,不要实现任何数据发送功能(
fetch/AJAX)。
第 6 步:收尾
在最后一个阶段确认后:检查整个页面在所有宽度下的效果,删除临时文件和文件夹(assets/_raw/、整个 .screens/),停止后台运行的本地服务器,删除未使用的样式和图像。生成一个简短的总结报告。
图像
- 从 Figma MCP 的响应中获取区块的资源(
get_design_context中的图像链接)。如果返回的是localhost地址,则直接下载。不要使用占位图或第三方图标集。 - 下载到临时文件夹
assets/_raw/<block>/中,位图图像尺寸为布局中实际尺寸的 2 倍(2x)。 - 响应式图像: 如果区块的移动版使用了裁剪后的图像(不同比例)或含义不同的图像,则同时下载两个版本(如
hero-bg-desktop.webp和hero-bg-mobile.webp),并通过<picture>元素引入。 - 分类处理:
- 交互式元素(按钮、链接)内的小型图标,需要在悬停时改变颜色(
fill/stroke)→ 在 HTML 中以内联<svg>形式嵌入,并设置fill="currentColor"(或通过 CSSmask-image); - 静态图标、Logo、简单的图形 → 通过
<img>标签放入assets/icons/(如果是大型图形,则放入区块文件夹)。如果图标是位图格式,请告知用户; - 照片和复杂图像 → 转换为 WebP 格式并放入
assets/<block>/。
- 交互式元素(按钮、链接)内的小型图标,需要在悬停时改变颜色(
- 转换为 WebP 格式,质量设置为 80。尝试顺序如下:
npx -y sharp-cli -i in.png -o out.webp -f webp -q 80(需要 Node.js);cwebp -q 80 in.png -o out.webp;- 如果以上都不可用,则保留原始格式,并仅一次告知用户需要安装的工具(Node.js 或
cwebp),无需停止工作。
- 如果转换后的 WebP 文件比原始文件还大,则保留原始文件。
- 文件命名:使用拉丁字母、小写、连字符分隔、具有描述性(如
hero-photo.webp、arrow-right.svg)。 - 区块确认后,删除
assets/_raw/<block>/文件夹。
悬停效果、动画、滑块
- 悬停效果: 基本按钮和链接的规则来自
AGENTS.md中的「UI 状态」行。如果区块中有独特的交互卡片/元素,而布局中未定义其状态,则不要自行设计,应在区块报告中询问用户。 - 滚动动画和自定义动画——仅在用户明确要求时添加。首先明确具体要实现的效果。简单动画(如滚动时淡入)使用
IntersectionObserver;复杂动画(如基于滚轮、粘性区块、视差效果)使用通过 CDN 加载的 GSAP,且需获得用户同意。始终考虑prefers-reduced-motion设置。 - 滑块: 简单滑块(箭头、指示点、滑动)——使用 CSS
scroll-snap和少量 JS 自行实现。复杂滑块(无限循环、自动播放、特效、联动滑块)——使用通过 CDN 加载的 Swiper。
常见问题
- Figma 响应被截断 → 对区块调用
get_metadata,然后对其子节点调用get_design_context。 - 看不到区块的移动版配对或移动菜单框架 → 询问用户,不要自行假设。
- 字体宽度与布局不匹配 → 检查字重和
letter-spacing,不要调整字体大小。 - 图像无法下载 → 检查 Figma MCP 是否正在运行;直接使用链接,不做修改。
- 截图中字体或图标丢失 → 检查服务器是否在
localhost:3000上运行,截图是否来自该服务器,而不是file://。 - 脚本报告「水平滚动」 → 找到超出屏幕宽度的元素(固定宽度、过大的
gap、超出边缘的装饰元素)并修复;对于超出边缘的装饰元素,在其区块上使用overflow-x: clip。 - 出于可访问性或技术限制而偏离布局 → 允许,但需在区块报告中说明。