
🎯 学生产级设计实现:不是把设计图"看着差不多"地写成 HTML/CSS,而是用 Pretext 排版引擎实现真正的文本计算——文字在缩放时真实重排、高度自适应内容、卡片自定尺寸。 ⏱️ 预计时间:35 分钟
[!quote]- 📖 原Skill精要 技能名称:design-html 核心功能:设计最终化——生成生产级 Pretext 原生 HTML/CSS。配合 [[L6-11-设计方案散弹枪|design-shotgun]] 审批后的原型、[[L6-02-CEO战略评审|plan-ceo-review]] 的 CEO 计划、或全新描述使用。文字真实重排、高度计算精确、布局动态化。30KB 开销,零依赖。 所属体系:gstack 虚拟工程团队 协作关系:任何计划类 Skill 的后置实现步骤——拿到方案后一键转为生产代码
1. 课程概览
💡 白话小课堂:design-html 解决的是一道"最后一公里"难题——设计定了、方向批了,但把它变成可运行的网页代码,传统方式是"打开 Figma、手动量间距、手写 HTML/CSS、反复调",这是体力活。design-html 把这个过程自动化:读入获选的设计方向、提取设计 token、选择正确的 Pretext 排版层级、生成语义化 HTML——而且文字是真的在正确排版的(不是 CSS 近似,是 Pretext 计算出的精确布局),最后启动实时预览让用户逐轮精细化,用 Edit(而非 Write)保留用户的手动文本编辑。
2. 为什么需要 Pretext?
The Text Layout Problem
传统 CSS 的文本布局受限于浏览器引擎的"黑盒"测量: → 你无法精确知道一段文字在特定宽度下会有多高 → 你无法让卡片高度精确匹配内容(除非用 JS 手动计算) → 你无法在 Canvas/SVG 中做正确的文字排版 → 聊天泡泡的宽度无法"紧贴"文字(CSS 只能全宽或内联)
Pretext(@chenglou/pretext)解决的就是这个问题: → prepare(text, font) → 一次性文本测量 → layout(handle, width, lineHeight) → 次毫秒级的布局计算 → 可以在 resize、contentEditable、动态内容变化时重复调用 → 30KB 开销,零依赖
design-html 的使命:生成"文字真的在正确工作"的 HTML。 不是 CSS 近似——是计算出的布局。
3. 输入检测与智能路由
design-html 能接受多种输入上下文,并根据已有上下文智能路由:
Case A: approved.json 存在(design-shotgun 已运行)
→ 读取获选变体 PNG 作为视觉参考 → 读取 CEO plan(如果有,增加战略上下文) → 读取 DESIGN.md(设计 token 优先于视觉提取) → 已有 finalized.html?→ 询问:在已有基础上演化 vs 重新生成
Case B: CEO plan 或设计变体存在,但没有 approved.json
→ 读取已有上下文(plan / variants / DESIGN.md) → 询问:运行 design-shotgun 探索 / 跳过模型图直接 HTML / 提供 PNG
Case C: 什么都没有(干净的开始)
→ 询问:先做策略规划 / 先做设计评审 / 直接视觉探索 / 口头描述
路径总结
→ approved-mockup 模式:有获选的 PNG 作为视觉参考 → plan-driven 模式:plan 是唯一的信息来源 → freeform 模式:用户口头描述 → evolve 模式:在已有的 finalized.html 上迭代
4. Pretext 层级与 API 路由
不同的设计类型需要不同的 Pretext API。design-html 自动分析设计并选择正确的层级:
Pretext 层级选择
| 设计类型 | Pretext API | 关键能力 |
|---|---|---|
| 简单布局(landing, marketing) | prepare() + layout() | 缩放感知的高度计算 |
| 卡片/网格(dashboard, listing) | prepare() + layout() | 自定尺寸卡片 |
| 聊天/消息 UI | prepareWithSegments() + walkLineRanges() | 紧贴泡泡、最小宽度 |
| 内容密集(编辑、博客) | prepareWithSegments() + layoutNextLine() | 文本绕过障碍物 |
| 复杂编辑 | 全引擎 + layoutWithLines() | 逐行手动渲染 |
四个核心 Pretext 模式
Pattern 1: 基础高度计算
// 1. 准备(一次性,字体加载后)
const prepared = new Map()
for (const el of elements) {
prepared.set(el, prepare(el.textContent, getComputedStyle(el).font))
}
// 2. 布局(廉价,每次 resize 调用)
function relayout() {
for (const [el, handle] of prepared) {
const { height } = layout(handle, el.clientWidth, lineHeight)
el.style.height = `${height}px`
}
}
// 3. 缩放感知
new ResizeObserver(() => relayout()).observe(document.body)
// 4. 可编辑内容
new MutationObserver(() => {
prepared.set(el, prepare(el.textContent, font))
relayout()
}).observe(el, { characterData: true, subtree: true })
Pattern 2: 紧贴容器(聊天泡泡)
→ 二分搜索找到产生相同行数的最窄宽度 → 泡泡不再"所有消息一样宽"——真的紧贴文字
Pattern 3: 文本绕过障碍物
→ layoutNextLine 迭代器允许每行不同最大宽度 → 文字真正流绕图片、引用块、侧边栏
Pattern 4: 逐行渲染
→ layoutWithLines 返回 {lines: [{text, width, x, y}...], height} → 用于 Canvas/SVG 渲染或自定义 DOM 定位
5. 生成与优化循环
HTML 生成要求
始终包含: ✅ Pretext 源码(内联或 CDN) ✅ CSS 自定义属性(从 DESIGN.md 或 Step 1 提取) ✅ Google Fonts via + document.fonts.ready 门控 ✅ 语义 HTML5(
, , ,绝不包含(AI 懒人黑名单): ❌ 默认紫色/蓝色渐变 ❌ 通用三列功能网格 ❌ 无视觉层级的居中布局 ❌ 不来自模型图的装饰性 blob/波浪/几何图形 ❌ 库存照片占位 div ❌ "Get Started" / "Learn More" 通用 CTA ❌ 带阴影的圆角卡片作为默认组件 ❌ emoji 作为视觉元素 ❌ 通用推荐区块 ❌ cookie-cutter hero(左文右图)
⚠️ 避坑指南: AI 生成 HTML 最常见的毛病是"lorem ipsum 占位"和"紫色渐变"。用真实内容填充——真实的产品名、真实的价格、真实的用户评价——你才能知道文字溢出在哪里、卡片会不会被长标题撑破。
6. 实时预览与精细化
实时预览服务器
→ 生成 HTML 后启动 python3 -m http.server → 用户浏览器中实时预览 → 每次 Edit 后刷新浏览器即可看到变化
验证截图
→ 如果 $B 可用:在 375px / 768px / 1440px 三个视口截图 → 内联展示给用户(Read 工具) → 检查:文字溢出、布局崩溃、响应式断裂
精细化循环(最多 10 次迭代)
LOOP:
- 用户打开浏览器中的 HTML
- 如果有获选模型图 → 内联展示做视觉对比
- AskUserQuestion:有什么需要改的?说"done"结束
- 如果"done" → 退出循环
- 应用反馈(用 Edit 做手术式修改,不重写整个文件)
- 简短总结变更(2-3 行)
- 如果有验证截图 → 重新截图确认
- 回到 LOOP
为什么用 Edit 而非 Write? → 用户可能通过 contenteditable 手动编辑了文本 → 重写整个文件会丢失这些手动修改 → 手术式编辑保留了用户的改动
🔑 核心秘诀:精细化循环用 Edit 而不是 Write——这是关键设计决策。
7. 设计 Token 提取与持久化
自动提取设计 token
→ 如果没有 DESIGN.md → 从生成的 HTML 中提取:
- CSS 自定义属性(颜色、间距、字号)
- 使用的字体族和字重
- 色彩调色板(主色、辅色、强调色、中性色)
- 间距比例尺
- 圆角值
- 阴影值 → 询问是否创建 DESIGN.md
保存元数据
→ finalized.json 记录:
- source_mockup(获选变体 PNG 路径或 null)
- source_plan(CEO plan 路径或 null)
- mode(approved-mockup / plan-driven / freeform / evolve)
- pretext_tier(选择的 Pretext 层级)
- framework(vanilla / react / svelte / vue)
- iterations(精细化迭代次数)
- screen / branch / date
8. 结构拆解:设计稿转代码 Skill 模板
设计稿转代码型 Skill 模板
核心特征
→ 管理对象 = 从设计原型到生产级 HTML/CSS 代码的转换流水线 → 核心原则 = Pretext 精确文本计算 + 智能路由模式选择 + 手术式迭代修改 → 关键设计 = 四模式输入检测(approved-mockup / plan-driven / freeform / evolve)、 四层 Pretext API 路由、生成规范黑白名单、实时预览精炼循环
通用结构
Input Detection & Routing(输入检测与路由)
- 检测 approved.json / CEO plan / DESIGN.md / finalized.html
- 按已有上下文选择模式:approved-mockup / plan-driven / freeform / evolve
- 模式决定后续所有步骤的起点和约束
Pretext Tier Selection(排版层级选择)
- 分析设计类型 → 选择 Pretext API 层级
- Pattern 1: prepare()+layout() → 基础高度计算(卡片/网格)
- Pattern 2: prepareWithSegments()+walkLineRanges() → 紧贴容器(聊天)
- Pattern 3: prepareWithSegments()+layoutNextLine() → 文本绕流(编辑/博客)
- Pattern 4: layoutWithLines() → 逐行渲染(Canvas/SVG)
HTML Generation Protocol(HTML 生成协议)
- MUST 清单:语义 HTML5、响应式、ARIA、暗色模式、真实内容
- NEVER 清单:紫色渐变、lorem ipsum、通用 CTA、圆角卡片默认组件
- 设计 token 驱动:CSS 自定义属性、字体加载门控、断点系统
Refinement Loop(精细化循环)
- 启动 http.server 实时预览 → 最多 10 次迭代
- 使用 Edit(手术式修改)而非 Write(保留用户手动编辑)
- 验证截图(375px/768px/1440px)→ 检查溢出/崩溃/断裂
Token Extraction & Persistence(Token 提取与持久化)
- 自动提取 DESIGN.md(颜色/间距/字体/圆角/阴影)
- 写入 finalized.json 记录(模式/层级/框架/迭代次数)
9. 电商 Skill 案例:设计稿转代码——活动落地页
🛒 实战案例:618大促前,某电商平台设计师在Figma中完成了"精华液专场"活动落地页的设计稿(移动端375px为主,含Hero顶图+3款主推商品卡片+限时倒计时条+底部固定CTA按钮)。设计总监确认了设计方案,现需将设计稿转为前端代码(Vue.js + Tailwind CSS),且必须像素级还原。
design-html从设计稿到可运行代码的完整流程:
- 输入检测:检测到
approved.json存在(design-shotgun已确定"实验室解谜风"方向),自动读取DESIGN.md中的设计Token——展示字体DM Serif Display、数据字体IBM Plex Mono、主色#1A1A2E、强调色#00C9A7、背景#F7F7F2、间距基准8px、最大内容宽度960px。- Figma解析:通过Figma API读取设计稿节点结构,识别出7个关键区域——Hero区(渐变背景+主打标题+CTA按钮)、倒计时条(红色#EF4444+等宽字体数字)、3张商品卡片(产品图+名称+核心成分标签+价格+已售数量)、底部固定CTA("立即抢购 ¥299"按钮)。自动识别了6个设计Token与Figma节点的映射关系。
- Pretext自适应排版:商品标题和描述文本长度不一,使用Pretext引擎为每段文本预计算渲染高度——layout(handle, cardWidth=343px, lineHeight=1.5)→返回精确高度。确保3张商品卡片即使描述长度不同(48字/72字/35字),卡片整体高度仍然一致(340px),不会出现参差不齐。
- 响应式断点:375px移动端——单列纵向滚动,商品卡片全宽343px,Hero标题20px粗体;768px平板——双列商品卡片并排,Hero标题28px;1440px桌面——三列布局,最大内容宽度960px居中。三个断点的间距和内边距均基于8px基准缩放。
- 代码质量检查:生成的Vue.js组件自动通过了Pretext精确度验证(设计稿中标注的文本行数vs代码渲染行数偏差<2%)、颜色对比度验证(CTA按钮白色文字#FFFFFF在#1A1A2E背景上对比度12.6:1远超AA标准4.5:1)、无障碍检查(倒计时数字加了aria-label="距离结束还有2小时15分钟")。
出码结果:1个Vue.js组件文件(197行)+ 1个Tailwind配置文件补充(15行)。设计还原度检查——使用design-review的像素对比工具,Figma设计稿vs浏览器渲染截图的像素差异率为0.7%(行业可接受标准<2%)。移动端Lighthouse性能评分93/100(图片使用WebP格式+懒加载),首屏渲染时间1.2秒。
🔑 启示:设计稿转代码最难的不是"把视觉还原"——而是处理文本长度不一致导致的卡片高度参差、响应式断点下的信息优先级变化、以及设计稿中的固定像素值在4K屏上变成蚂蚁字的问题。好的design-html流程在这些问题发生之前就通过Pretext和Token系统把它们解决了。
生成后自动提取并在 DESIGN.md 中补充:
→ 圆角值:图片 0px(直角),卡片 4px,按钮 4px
→ 阴影:卡片 box-shadow: 0 1px 3px rgba(26,26,46,0.08)
→ 过渡:all 150ms ease-out
→ 新增动效:hover 时卡片微微上浮(transform: translateY(-2px))
精细化循环迭代
迭代 1:创始人反馈——"成分表像药瓶标签,太冷了"
→ Edit:成分表添加暖灰背景底色 + 微圆角
→ 从"实验室报告"调整为"有温度的实验室报告"
迭代 2:用户测试反馈——"移动端成分表太长,需要折叠"
→ Edit:默认展示前 5 个成分 + "查看全部 15 个成分"按钮
→ Pretext 重新计算展开/折叠后的高度
迭代 3:done ✓
***
## 10. 掌握检验
**Q1**:Pretext 库的 `prepare()` 和 `layout()` 解决了 CSS 的什么根本性局限?
- A) CSS 不支持 Google Fonts
- B) CSS 无法精确告诉你一段文字在特定宽度下会有多高
- C) CSS 不支持暗色模式
- D) CSS 不支持响应式布局
**Q2**:在 design-html 的输入检测中,如果 `approved.json` 存在但 `finalized.html` 也已经存在,Agent 应该怎么做?
- A) 直接覆盖 finalized.html
- B) 忽略 approved.json,重新开始
- C) 询问用户:在已有 finalized.html 上迭代还是重新生成
- D) 自动回退到 plan-driven 模式
**Q3**:以下哪个场景需要使用 Pretext 的 `prepareWithSegments() + walkLineRanges()` 层级(Pattern 2)?
- A) 产品详情页的描述文字
- B) 数据仪表盘中的统计卡片
- C) 聊天界面的气泡消息
- D) 博客文章的长文本排版
**Q4**:为什么精细化循环中必须用 Edit 而非 Write?请描述一个具体场景:如果用了 Write 替代 Edit 会发生什么灾难?
**Q5**:"真实内容,绝不 lorem ipsum"不仅仅是审美要求。请从至少两个工程角度解释为什么用 lorem ipsum 填充内容会直接导致 Pretext 的精确排版失效。
**Q6**:design-html 的黑名单(绝不包含)中有"通用推荐区块"和"带阴影的圆角卡片作为默认组件"。请将这些反模式与 Pretext 的技术能力关联——为什么有了精确文本排版能力后,这些反模式变得更加不需要?
***
## 11. 答案
<details>
<summary>点击查看答案</summary>
**Q1**:**B** —— Pretext 解决的核心问题是文本布局的精确计算。
**Q2**:**C** —— 这是 evolve 模式。
**Q3**:**C** —— 聊天界面需要 Pattern 2(紧贴容器)。
**Q4**:如果用户在浏览器中通过 contenteditable 手动编辑了产品描述文本(改了几句话、调整了措辞),但设计上只需要修改一个按钮的颜色——这时如果用 Write 重写整个 HTML 文件,用户手动编辑的内容会全部丢失。用 Edit 只改按钮的颜色样式,保留用户在其他区域的所有手动修改。这就是"手术式修改"——只动需要动的部分。
**Q5**:①长度差异——lorem ipsum 的段落长度是固定的("Lorem ipsum dolor sit amet..."),而真实的产品描述可能是 50 字也可能是 200 字。用 lorem ipsum 测不出文字在极限长度下的卡片表现(短文字卡片空洞?长文字卡片撑破?)。②词长和换行点——lorem ipsum 的词长分布是拉丁语的(长词居多),而真实中文的词长完全不同。Pretext 的 layout() 计算分行点依赖于真实字符流——lorem ipsum 换出的行数和位置与真实内容不同,Pretext 计算的精确高度也会失准。最终结果:上线时发现"测试时好好的"是因为"测试用的是假文字"。
**Q6**:这些反模式之所以流行,正是因为传统 CSS 无法精确控制文本与容器的关系——设计师用圆角阴影卡片来"包装"内容的不确定性(你不知道文字会溢出多少,所以给一个圆角卡片兜底),用通用推荐区块来"填满"无法精确排版的空间。Pretext 赋予了对文本的精确控制——你知道每个文字块的确切尺寸,可以用精确的间距和层级替代模糊的"卡片式包装",用精确排版的数据展示替代"通用推荐区块"。有了精确排版能力,装饰性圆角卡片和通用区块就变成了不必要的设计遮盖,而非设计需要。
(5/6 通过)
</details>
***
## 延伸阅读
- [[L6-11-设计方案散弹枪|设计方案散弹枪 —— 一口气探索5个完全不同的设计方向]]
- [[L6-13-开发者体验审计|活网站开发者体验审计 —— 像用户一样体验你自己的API]]

评论区
共 0 条评论