首页
/ Impeccable /typeset 实战指南:在既有视觉世界内打磨字体层级、字面与阅读体验

Impeccable /typeset 实战指南:在既有视觉世界内打磨字体层级、字面与阅读体验

2026-09-08 10:03:58作者:田桥桑Industrious

排版承载着信息、层级与产品声音。对于使用 Impeccable 技能驱动 AI 编码助手(Claude Code、Cursor、Gemini CLI、Codex、Qoder 等)做前端界面设计的开发者而言,/impeccable typeset 是把"字体选择与层级"这一单项打磨到可交付质量的标准化工作流。本文基于 .qoder/skills/impeccable/reference/typeset.md 展开,梳理从"访客模式判定 → 双轨评估 → 系统设定 → 逐条应用 → 证据化验收 → Live 模式参数化"的完整链路,并给出仓库内可对照的源码、数据与测试证据,让读者既能照单执行一次排版评审,也能理解其背后的设计决策与工程约束。

typeset 在整个技能中的定位

在 Impeccable 的指令体系中,typeset 属于 Enhance(增强) 类目,SKILL.md 的命令表中将其描述为 "Improve typography hierarchy and fonts",统一入口是:

/impeccable typeset [target]

其核心边界在于第一条原则:排版承载信息、层级与声音,但一切改进都应发生在已确立的视觉世界之内;除非用户明确要求更换身份(identity),否则不要替换现有视觉身份。 这正是 typeset 与 new-work 的分界——如果更换字体意味着创造一个新的视觉身份,则应当路由到 new-work.md,并同步更新 DESIGN.md;反之则应保留已确认的字体族、优化其使用方式。

同一份参考文档在仓库中针对不同 AI 运行时被多路复制(.claude/.cursor/.gemini/.grok/.qoder/.opencode/skill/reference/plugin/skills/impeccable/reference/ 等),以便每种 harness 都能按统一契约加载;其中 skill/ 目录下的副本可视为基准源。技能总入口 SKILL.mdallowed-tools 也明确授权运行 node .qoder/skills/impeccable/scripts/* 这类脚本,这也是后文机械扫描命令能作为统一契约存在的原因。

第一步:先定访客模式(Visitor mode),再谈字体策略

typeset 的第一步不是挑字体,而是判断当前页面属于哪种访客模式,因为三种模式的排版优先级完全不同:

访客模式 排版策略重心
Persuade(说服)+ Experience(体验) 展示性字体(display type)可以承载品牌声音;当构图受益时,可用果断的对比(decisive contrast)与响应式字号阶(responsive scale)
Operate(操作)+ Read(阅读) 稳定、可扫描、行宽(measure)优先;往往一套经过精心调校的字体族 + 固定角色阶(fixed role scale)就是正确解
Native(原生) 遵循 ios.mdandroid.md,包括平台的字号缩放与无障碍行为

模式应按"表面(surface)"而非"产品类型"选择:工具页的落地页仍是 Persuade,时尚品牌的文档仍是 Read。同源规则也见于 operate.md 中对 Operate/Read 更深层的指引。文档对类型的"身份替换闸门"给出明确裁决:排版替换若会造成新身份 → 走 new-work.md;否则保留已确认的字体族,只改进其使用方式。

第二步:双轨评估——感知评审与机械扫描各自独立

当有子代理(sub-agent)工具可用且被允许时,typeset 要求把两类评估分开运行;即便没有子代理,也应由同一个代理按顺序独立执行。关键约束是:不要让检测器的发现先入为主地锚定设计评审的结论。

轨一:Typographic assessment(排版感知评审)

检查代表性页面与样式,并对下列每一问给出"文件 + 选择器 + 计算值"级别的证据:

  • 权威性与契合度(Authority and fit):已确立哪些字族、字重与角色?它们契合产品与所选视觉世界,还是未经审视的默认值?每个字体族是否都必要?
  • 层级(Hierarchy):标题、正文、标签(label)、元数据(metadata)、数据(data)角色能否一眼区分?相邻字号或字重是否过于接近、难以承担不同职能?
  • 字号阶与一致性(Scale and consistency):是精心设计的角色阶,还是一堆随意数值?重复角色在不同屏与状态间是否保持一致?
  • 阅读性(Reading):正文行宽是否落在舒适的 45–75 字符区间?行高、段落节奏、对比度与字距(tracking)是否针对真实字面、字宽、语言与表面做了调校?
  • 压力测试(Stress):长标题、本地化扩展(localization expansion)、缩放(zoom)、窄容器、缺失字重、字体回退(font fallback)时会发生什么?
  • 交付(Delivery):是否只加载被用到的资源?回退度量(fallback metrics)、加载策略、可变字体(variable-font)设置是否避免隐形文字与破坏性回流(reflow)?

仓库为"度量感知"提供了一处可验证的工程底座:.qoder/skills/impeccable/scripts/data/font-index.json 是一个面向字体的测量索引,其 schema 记录了测试文本(如 "The quick brown fox jumps over the lazy dog 0123456789 HAMBURGEVONS")、测量字号(48 / 14 / 48c)以及一整套感知特征键,包括 advancexRatio(x 高度比)、descRatiostemW(主干宽)、contrastserifroundFracrunDensity、按垂直与水平切分统计的剖面特征(vprof0-9hrun25-90vrun25-90)等,并将字体归入 sans / serif / display / handwriting / mono 类别,按 "字体名 + 字重" 逐条给出测量向量。这说明"行高要适配真实字面而非套用通用比例"这类规则在工程上是有数据支撑的——配套的 font-index-failures.json 则用于记录无法完成测量的字体集合,构成回退依据。

轨二:Mechanical scan(机械扫描)

按文档约定运行检测器,作用域限定在 typography:

node .qoder/skills/impeccable/scripts/detect.mjs --json --scope type [target files or dirs]

同时还需人工检查检测器无法解析的动态或任意字体取值。两份结论合成后再动手编辑,并记录"每一轨各自捕获了什么、漏掉了什么"。文档特别强调:一次干净的扫描只是地板(floor),不是好排版的证明。

仓库中 tests/fixtures/antipatterns/ 下的夹具也从侧面印证了该检测体系的存在与粒度——其中既有应被标记的反例(如 typography-should-flag.htmlextreme-negative-tracking.htmloverused-font.htmlundersized-ui-text.html),也有应放行的正例(typography-should-pass.htmlcss-in-prose-should-pass.html),还有对 em-dash 实体(em-dash-entities.html)、非渲染文本(nonrendered-text.html)等边缘情况的覆盖,可作为"机械扫描能发现什么"的补充观察。

第三步:Set the system——动手前先把系统说清楚

编辑前,typeset 要求代理先用文字陈述排印系统的设定,包括:

  • 界面需要的角色(roles);
  • 角色之间预期的对比强度
  • 阅读行宽与密度(measure and density);
  • 哪些既有字面与字重是权威的(authoritative);
  • 任何性能、本地化或无障碍约束

设定阶段的核心纪律是:用最少的角色与字体族把层级做到不容误读;刻意组合字号、字重、空间与音调,而不是让字号独自承担全部工作;角色名与 token 应描述用途而非取值。这与技能整体的 token/design-system 思路(可参考 extract.md 对抽取可复用 token 的描述)保持一致——排版角色先于排版数值而存在。

第四步:Apply——把规则落到 CSS 与内容上

应用阶段是一组可以直接作为评审 checklist 的硬规则:

  • 正文下限:正文保持舒适的可读性与可缩放性。普通网页正文以 1rem / 16px 为底(floor),除非密集角色、平台惯例或用户设置能给出更低的正当理由。
  • 行宽:散文段落保持在 45–75ch;行高与行宽大致反向调节——更宽的版面通常需要更大的行距。
  • 深色表面上的浅色文字:在三个感知轴上都做补偿——行高略增、字距略松、当字面需要时字重再加一档。
  • 行高依字面而定:按真实字面、字宽、语言与对比度调节,而不是套一个"万能比例"。
  • 一致性:重复角色在不同屏与状态间保持一致。
  • 特性使用:当内容受益时使用数字(numeric)、表格(tabular)、代码(code)与标签(label)等 OpenType 特性。
  • 加载策略:只加载被使用的字体资源与字重;提供度量兼容的回退字体(metric-compatible fallbacks),避免阻塞文本显示。
  • 空间响应:营销展示字可以按可用空间响应;密集产品与阅读表面应保持空间上的可预测性。
  • 无障碍:保留浏览器缩放、用户字体设置、iOS Dynamic Type 与平台文本缩放。
  • 段落节奏:用段落间距或首行缩进作为主要段落节奏;两者同时使用通常会双重标记边界。

可以翻译成 CSS 形态的常见落地示例(此处为模式示意,非仓库内代码):

/* 正文以 1rem/16px 为底,行宽 45–75ch */
body { font-size: 1rem; line-height: 1.6; }
article p { max-width: 65ch; }

/* 行高随行宽反向调节:窄栏用小行距、宽栏用大行距 */
.prose { max-width: 45ch; line-height: 1.45; }
.prose--wide { max-width: 75ch; line-height: 1.7; }

文档同时划出两条红线:不要让字型装饰凌驾于可理解性之上;也不要在没有明确角色分工的情况下引入第二个字体族——一个字体族必须拥有"只有它能承担的清晰职能"。

第五步:Verify——证据化验收,拒绝"裸 yes"

验收不是口头确认,而是逐条用渲染或源码证据作答后再重跑机械扫描:

  • 主级、次级、正文、元数据角色在不读正文的情况下也能被认出;
  • 长文本在相关宽度与语言下保持舒适;
  • 排版归属于产品及其已确立的视觉世界;
  • 加载过程不产生破坏性回流或隐形文字;
  • 缩放、文本缩放、焦点、对比度与收窄视口路径仍然可用;
  • 最终机械扫描无未解释的发现。

当层级成立后,文档规定交棒给 /impeccable polish 做最终交付前质量收尾——对应技能参考 polish.md

第六步:Live 模式下的排版参数契约

当 typeset 在 live.md 描述的 Live 变体模式(在浏览器中选择元素、生成 HTML+CSS 变体并通过 dev server 的 HMR 热切换)中被调用时,存在一条强制的参数签名:

每个变体都必须声明一个粗粒度(coarse)的 scale 参数,并把字号阶(type ramp)写成基于 var(--p-scale, 1) 的公式。

参数 schema 原文如下:

{"id":"scale","kind":"range","min":0.85,"max":1.3,"step":0.05,"default":1,"label":"Scale"}
  • kind: "range" 表示滑块类参数,驱动一个 CSS 变量 --p-scale
  • min/max/step/default 定义了滑块的取值范围(0.85–1.3)、步进(0.05)与默认值(1);
  • label 决定浏览器内嵌控件显示的文字。

排版实践上,可将整条字号阶梯写成对 scale 的缩放:

:root { --p-scale: 1; }
.hero-title {
  font-size: calc(clamp(2.5rem, 6vw, 5rem) * var(--p-scale, 1));
  line-height: calc(1.05 / (1 + (var(--p-scale, 1) - 1) * 0.4));
}

live.md 的参数契约还给出了额外的预算约束:参数按"组合的视觉重量"配给(叶级/极小元素 0 个参数,中等组合约 2 个,大型组合 2–3 个、最多 4 个),有三种参数种类——range(驱动 --p-<id>)、steps(分段单选,驱动 data-p-<id>)、toggle(同时驱动变量与属性)。具体到 typeset,live.md 在"动作特异性变体"一节明确要求:typeset 的每个变体必须使用不同的字体配对(pairing)且搭配不同的字号比例(scale ratio)。此外,只有当"配对或字重"代表真实系统选择时,才允许追加至多一个 pairing 或 weight 参数;任何追加参数都必须遵守 live.md 的参数契约。

小结:把 typeset 当作可执行的排版质量闭环

综上,/impeccable typeset 提供了一条可重复的质量闭环:判定访客模式 → 感知评审与机械扫描双轨独立取证 → 显式设定排印系统 → 在既有身份内逐条应用规则 → 证据化验收并交棒 polish → 在 Live 模式中把 scale 参数化供人在浏览器内实时微调。它既反对"用一套默认值糊弄排版",也反对"脱离既有视觉世界另起炉灶";既承认机械扫描的价值,又清醒地把干净扫描定义为地板而非终点。对于希望在 AI 驱动的界面开发中稳定产出高质量字排版的团队,这份参考文档配合仓库中的字体度量数据(font-index.json)、检测夹具(typography 相关 tests fixtures)与 live.md 参数契约,正好构成一套可引用、可验证、可执行的完整工具箱。

若需深入其他维度,可在 SKILL.md 的命令表中找到与 typeset 相邻的 layoutauditcritiquepolish 等指令的参考入口;同类参考文档的基准源位于 skill/reference/typeset.md

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391