排版
整套语言只用一个反直觉的规则建立性格:默认字体是等宽,只有标题、卡片标题、表头和统计大数字 切到无衬线。因此正文、按钮、导航、表单控件、元信息全部是 mono——如果你从 sans 基线起手,复刻出来的观感会完全不同。
等宽 vs 无衬线
分工表就是全部规则。没有第三档字体,也不按"重要性"挑字体。
| 角色 | 字体 | 依据 |
|---|---|---|
| 正文段落 | mono | body 默认字体,从未被覆盖 |
| 按钮 | mono | .zz-btn { font-family: var(--zz-font-mono) } |
| 导航链接 | mono | 不声明字体,继承 body |
| 表单控件 | mono | 输入框、Select 触发器与选项 |
| 元信息 / 日期 / 计数 | mono | 另加 tabular-nums |
| 行内 code 与代码块 | mono | code / kbd / samp / pre |
| h1–h6 标题 | sans | 全局规则,字距 -0.015em |
| 卡片标题 | sans | 显式声明 font-sans |
| 表头 th | sans | .zz-spec thead th { font-weight: 600 } |
| 统计大数字 | sans | 唯一允许 font-bold 的地方 |
mono · 正文 / 界面(默认)
Handle 大小写敏感,数字 0123456789 等宽对齐。
sans · 只用在这些角色
标题、卡片标题、表头、统计数字。
最容易抄错的一条:按钮和导航是等宽。它们不声明 font-family,直接继承body 的 mono;只有显式写 font-sans 的元素才走无衬线。所以要往 sans 上"修正"按钮, 方向是反的。
标题阶梯
下面用真实标签渲染。标题一律 font-weight 600、line-height 1.2、letter-spacing -0.015em;h6 是唯一例外,它是大写小标签而不是标题。
页面标题 H1
区块标题 H2
子区块标题 H3
卡片组标题 H4
最小标题 H5
大写小标签 H6
演示块里出现了真实的 <h1>。真实页面里一个文档应只有一个 h1,其余从 h2 起往下排, 不要为了字号跳级——要字号就改类名,不要改标签。
| 标签 | 字号 | 使用场合 |
|---|---|---|
h1 | 2.25rem / 36px | 内页标题,一页一个 |
h2 | 1.75rem / 28px | 区块标题 |
h3 | 1.375rem / 22px | 子区块标题 |
h4 | 1.125rem / 18px | 卡片组标题 |
h5 | 1rem / 16px | 最小标题 |
h6 | 0.875rem / 14px | 大写小标签(同时是 muted 色) |
字号阶梯
十档像素值,全部映射到 rem。挑字号就是挑用途,不要在两档之间插任意值。
| px | rem | 用途 |
|---|---|---|
10px | 0.625rem | eyebrow 小标签、侧栏分组标题 |
11px | 0.6875rem | 顶栏脚注、字标内文字、极小标记 |
12px | 0.75rem | 元信息、日期、计数、代码块、规格表 |
13px | 0.8125rem | 导航链接、次级 UI 文案、注释、图注 |
14px | 0.875rem | 按钮、表单控件、卡片标题、h6 |
15px | 0.9375rem | 正文(body 默认)、页面 lede、大号按钮 |
16px | 1rem | h5、面板内小标题 |
18px | 1.125rem | h4、区块小标题、徽章名 |
24px | 1.5rem | 大区块标题(大屏升到 28px)、主题卡标题 |
30px | 1.875rem | 统计大数字、空状态大文案 |
标题档的 22 / 28 / 36px 不在这张表里,它们由 h3 / h2 / h1 固定承担。
角色配方
把 token 组合成四种固定角色,直接复制:
eyebrow 小标签
基础 / 排版正文段落
正文用 0.9375rem、行高 1.6、颜色 --zz-text-secondary,最大宽度 var(--zz-measure)(48rem)。 行内 code 与正文同族,因此不会产生字体突跳。
元信息行
行内 code
改主题只需要写 data-theme="light" 一个属性。
<!-- eyebrow:0.625rem / uppercase / letter-spacing 0.18em / 品牌色 -->
<span class="zz-doc__eyebrow">基础 / 排版</span>
<!-- 正文:0.9375rem / line-height 1.6 / --zz-text-secondary -->
<p class="zz-doc__lede">正文…</p>
<!-- 元信息:0.75rem / --zz-text-muted / tabular-nums -->
<p style="font-size:0.75rem;color:var(--zz-text-muted);font-variant-numeric:tabular-nums">
2026-10-15 · 1,204 字
</p>行高与字距
| 对象 | 行高 | 字距 | 备注 |
|---|---|---|---|
| 正文(body) | 1.6 | 默认 | 0.9375rem 正文的默认节奏 |
| 长文 / lede | 1.65 | 默认 | 整段阅读时再松一点 |
| 卡片正文 | 1.625 | 默认 | 13px 卡片内文 |
| 紧凑行 | 1.375 | 默认 | 标题+副标题成对出现时 |
| 标题 h1–h6 | 1.2 | -0.015em | 无衬线大字号必须收紧 |
| eyebrow / 小标签 | 继承 | 0.18em | 配 uppercase |
| h6 小标签 | 继承 | 0.08em | 配 uppercase,不配 muted 以外颜色 |
| 纯数字 / 图标 | 1 | 默认 | 只在这种情况下允许压到 1 |
正文字号从不是任意值:15px 是正文基准,14px 是控件基准,12px 是元信息基准。三档之外的语境,先用现有档位凑,凑不出来说明结构该拆。