Communitygithub.com

biplineX/figma-landing

将 Figma 中的落地页设计逐块转换为纯 HTML/CSS/JS 代码,每完成一块需用户确认。

figma-landing 是什么?

此技能用于将 Figma 设计稿转换为纯 HTML、CSS 和 JS 的静态落地页。其核心工作流程为逐块构建:每完成一个页面区块后,代理会暂停并等待用户确认,以确保最终结果精确符合预期。技能支持桌面端和移动端框架,并集成了 Figma MCP 工具来获取元数据、设计上下文和截图,从而提取精确的尺寸、颜色和图像资源。它还包含详细的图像处理指南(例如,将图标转换为内联 SVG,以及将图像转换为 WebP 格式),并且内置了通过 Playwright 进行屏幕截图对比的自检机制。该技能特别适合那些需要将 Figma 设计忠实转化为生产级代码、同时希望保持对布局和交互控制的开发者和设计师。

兼容平台~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/biolineX/figma-landing/tree/HEAD

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

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 步:布局结构图

  1. 对链接中的节点调用 get_metadata(对于整个文档,不传 node-id 或传入根页面)。
  2. 找到落地页的框架版本:桌面版、移动版,有时还有平板版。从布局中确定宽度,不要使用默认值。同时找到页面上可能单独存在的模态窗口(弹出框)和打开的移动菜单框架。
  3. 在每个框架内,识别顶层的区块(页眉、英雄区、优势、评价、页脚等)。
  4. 在各版本之间匹配区块:「桌面区块 ↔ 移动区块」(根据图层名称、顺序和内容)。
  5. 向用户展示结构图并等待确认:
宽度:桌面 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

  1. 如果项目根目录中没有 AGENTS.md,则从技能文件夹复制 templates/AGENTS.md。根据第 2 步的数据填写其中的「此落地页」部分(宽度、容器、字体)。断点保留默认值;仅当此布局在其他宽度下出现问题时才进行修改,并记录新的断点。
  2. 创建目录结构:index.html、style.css、script.js、assets/icons/。
  3. index.html:<!doctype html>、lang="ru"、charset、viewport、<title> 和 <meta name="description"> 根据落地页内容填写。不添加 favicon。script.js 使用 defer 属性引入。
  4. 字体:从 get_design_context/get_variable_defs 中获取,仅通过 Google Fonts 引入所需的字重,使用 display=swap。如果字体不在 Google Fonts 中,则向用户请求字体文件,通过 assets/fonts/ 下的 @font-face 引入。
  5. style.css:样式重置(参见 AGENTS.md),然后是 :root,包含颜色、字体、间距、容器宽度的变量。如果布局中有变量,则从 get_variable_defs 中取值;否则从布局中提取并取整。
  6. 基础组件:将布局中通用的元素(按钮、区块标题、输入框)提取为可复用的类(.btn、.section-title、.input、.container)。如果布局中没有包含状态(hover、focus、active)的 UI 组件库,仅一次询问用户整个项目中对通用按钮和链接的悬停规则。将回答记录到 AGENTS.md 的「此落地页」部分中的「UI 状态」一行。
  7. 工具(仅一次):
    • 在后台从项目根目录启动本地服务器:npx -y serve -l 3000(备选方案:python3 -m http.server 3000)。所有截图都从 http://localhost:3000 获取,而非 file://;
    • 检查截图工具:如果已连接 Playwright MCP,则使用它;否则使用 scripts/shot.cjs 脚本(参见「自我检查」);
    • 检查图像转换器(参见「图像」)并记录结果。
  8. 通知用户骨架已就绪,然后转到第一个区块。

第 4 步:逐块构建

对于结构图中的每个区块,严格从上到下按顺序进行(包括包含表单的区块):

  1. 数据。 获取桌面区块及其移动版配对区块的 get_design_context 和 get_screenshot。
    • 如果响应被截断或过大,则对该区块调用 get_metadata,并逐个获取其子节点。
    • 响应中的代码(通常是 React + Tailwind)仅作为尺寸、颜色和结构的参考。不要复制其样式。
  2. 图像。 下载并处理该区块的资源(参见「图像」)。
  3. 布局。 在 index.html 中编写该区块的 HTML,在 style.css 中通过带注释的部分编写样式(例如 /* ===== hero ===== */),在 script.js 中编写 JS(如果需要)。使用第 3.6 步中的基础类,不要复制按钮和标题的代码。先编写桌面版,然后通过 clamp() 和媒体查询实现响应式布局,直至移动版。
    • 对于移动宽度的 header,立即构建汉堡菜单(根据结构图中的框架或询问用户的具体样式)。
    • 如果区块包含表单,请使用基本的浏览器验证属性(required、type="email"、type="tel"、pattern)进行布局,但不要包含 JS 提交逻辑。
  4. 自我检查。 在桌面、移动和中间宽度(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. 报告与暂停。 简要告知用户已完成内容、与布局的偏差及原因、需要为区块中独特的交互元素(如非标准卡片悬停效果、滑块参数)澄清的内容。等待确认。 将用户的修改应用到此区块,然后再次等待。
  6. 仅在收到「确认」后,再进入下一个区块。

第 5 步:模态窗口和表单逻辑

在所有主要区块布局完成后:

  1. 如果在第 2 步中发现了隐藏的模态窗口(弹出框),则构建它们,并实现打开/关闭触发器(按钮、Esc 键、点击遮罩层)。行为遵循 AGENTS.md 中的「JavaScript」部分。
  2. 每个窗口作为一个独立区块: 在打开状态下进行截图自检、报告并等待确认。
  3. 检查页面上所有表单的功能。在用户明确请求并提供 API 地址或技术任务说明之前,不要实现任何数据发送功能(fetch/AJAX)。

第 6 步:收尾

在最后一个阶段确认后:检查整个页面在所有宽度下的效果,删除临时文件和文件夹(assets/_raw/、整个 .screens/),停止后台运行的本地服务器,删除未使用的样式和图像。生成一个简短的总结报告。

图像

  1. 从 Figma MCP 的响应中获取区块的资源(get_design_context 中的图像链接)。如果返回的是 localhost 地址,则直接下载。不要使用占位图或第三方图标集。
  2. 下载到临时文件夹 assets/_raw/<block>/ 中,位图图像尺寸为布局中实际尺寸的 2 倍(2x)。
  3. 响应式图像: 如果区块的移动版使用了裁剪后的图像(不同比例)或含义不同的图像,则同时下载两个版本(如 hero-bg-desktop.webp 和 hero-bg-mobile.webp),并通过 <picture> 元素引入。
  4. 分类处理:
    • 交互式元素(按钮、链接)内的小型图标,需要在悬停时改变颜色(fill/stroke)→ 在 HTML 中以内联 <svg> 形式嵌入,并设置 fill="currentColor"(或通过 CSS mask-image);
    • 静态图标、Logo、简单的图形 → 通过 <img> 标签放入 assets/icons/(如果是大型图形,则放入区块文件夹)。如果图标是位图格式,请告知用户;
    • 照片和复杂图像 → 转换为 WebP 格式并放入 assets/<block>/。
  5. 转换为 WebP 格式,质量设置为 80。尝试顺序如下:
    1. npx -y sharp-cli -i in.png -o out.webp -f webp -q 80(需要 Node.js);
    2. cwebp -q 80 in.png -o out.webp;
    3. 如果以上都不可用,则保留原始格式,并仅一次告知用户需要安装的工具(Node.js 或 cwebp),无需停止工作。
  6. 如果转换后的 WebP 文件比原始文件还大,则保留原始文件。
  7. 文件命名:使用拉丁字母、小写、连字符分隔、具有描述性(如 hero-photo.webp、arrow-right.svg)。
  8. 区块确认后,删除 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。
  • 出于可访问性或技术限制而偏离布局 → 允许,但需在区块报告中说明。

相关技能