sai-assets可复用网页资产库 GitHub

CJK Thin Type System · 中文细体排版语言

cjk-thin-type-systemv1.0.0 排版 MIT(本包 JSON / 文档 / 断言为自产)

中文 / 日文暗色单页站、作品集、个人站要求「细、干净、一套语言」时;或已有站点出现「字体乱」(同一字号挂多字重、各组件一套行高 / 字距 / 阴影)需要先普查再收敛时

不适用场景

明亮纸媒长文(走 cjk-typography 的正文档 + 衬线 article 栈)、数据密集工具面板(走系统栈)、需要粗体力量感的营销落地页

新窗口 ↗
载入预览…

卡片与舞台里跑的是包内真实的预览页;WebGL 类需点“运行预览”才会建立渲染上下文。

元数据

类目
排版配方
版本
v1.0.0
许可
MIT(本包 JSON / 文档 / 断言为自产)
规模
13 文件 · 43 KB
来源项目
asset-source · fonts/cjk-thin-type-system.json

标签

  • cjk
  • typography
  • thin
  • type-scale
  • dark
  • letter-spacing
  • line-height
  • text-shadow

验证证据

2026-11-03 · python packs/cjk-thin-type-system/scripts/assert_tokens.py

PASS assert_tokens cjk-thin-type-system / scale 4 · weights 2 · tracking 3 · leading 3 · shadow 2 / probe: preview 2 文件 · 5 条 font-size 最小 12px · 最小行高 1.35 · vw 外推 0 · 斜体 0;负例 6/6 判失败(11px / 裸 4vw / clamp 上限 4vw / lh 1.2 / italic / min_px 15)

归属与许可

  • 本地素材库 · 字号阶梯与字重配对原子卡 · 自产观测(2026-10-31 全站排版普查)
    21 种样式组合 → 6 组规则的收敛样本与字重/字号/行高/影档位
  • sai-frontend §4 中文排版硬闸 · internal
    阴影至多一层、移动优先、中文回退链三条硬口径
  • Noto Sans SC / Fraunces(字族名引用) · OFL-1.1(Fraunces 待核)
    只引用字族名,包内不含字体文件;字族与回退栈见 cjk-typography 包

取用方式

固定版本(CDN)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/nakamotosai/sai-assets@pack/cjk-thin-type-system@1.0.0/packs/cjk-thin-type-system/css/default.css">
raw 直取(跟随 main)
curl -O https://raw.githubusercontent.com/nakamotosai/sai-assets/main/packs/cjk-thin-type-system/SKILL.md
仓库内落地
python scripts/apply.py cjk-thin-type-system --to <项目目录>
整包下载
https://assets.ouuut.com/downloads/cjk-thin-type-system.zip

源码与规则

pack.json
{
  "schema": 1,
  "id": "cjk-thin-type-system",
  "title": "CJK Thin Type System · 中文细体排版语言",
  "kind": "fonts",
  "category": "fonts",
  "version": "1.0.0",
  "license": "MIT(本包 JSON / 文档 / 断言为自产)",
  "attribution": [
    {
      "name": "本地素材库 · 字号阶梯与字重配对原子卡",
      "license": "自产观测(2026-10-31 全站排版普查)",
      "what": "21 种样式组合 → 6 组规则的收敛样本与字重/字号/行高/影档位"
    },
    {
      "name": "sai-frontend §4 中文排版硬闸",
      "license": "internal",
      "what": "阴影至多一层、移动优先、中文回退链三条硬口径"
    },
    {
      "name": "Noto Sans SC / Fraunces(字族名引用)",
      "license": "OFL-1.1(Fraunces 待核)",
      "what": "只引用字族名,包内不含字体文件;字族与回退栈见 cjk-typography 包"
    }
  ],
  "origin": {
    "project": "asset-source",
    "path": "fonts/cjk-thin-type-system.json",
    "derived_from": null
  },
  "entry": "SKILL.md",
  "files": {
    "tokens": [
      "tokens/index.json",
      "tokens/scale.json",
      "tokens/weights.json",
      "tokens/tracking.json",
      "tokens/leading.json",
      "tokens/shadow.json"
    ],
    "usage": "docs/usage.md",
    "assert": "scripts/assert_tokens.py",
    "preview": "preview/index.html"
  },
  "tags": ["cjk", "typography", "thin", "type-scale", "dark", "letter-spacing", "line-height", "text-shadow"],
  "when": "中文 / 日文暗色单页站、作品集、个人站要求「细、干净、一套语言」时;或已有站点出现「字体乱」(同一字号挂多字重、各组件一套行高 / 字距 / 阴影)需要先普查再收敛时",
  "not_for": "明亮纸媒长文(走 cjk-typography 的正文档 + 衬线 article 栈)、数据密集工具面板(走系统栈)、需要粗体力量感的营销落地页",
  "default_variant": null,
  "verified": {
    "date": "2026-11-03",
    "how": "python packs/cjk-thin-type-system/scripts/assert_tokens.py",
    "evidence": "PASS assert_tokens cjk-thin-type-system / scale 4 · weights 2 · tracking 3 · leading 3 · shadow 2 / probe: preview 2 文件 · 5 条 font-size 最小 12px · 最小行高 1.35 · vw 外推 0 · 斜体 0;负例 6/6 判失败(11px / 裸 4vw / clamp 上限 4vw / lh 1.2 / italic / min_px 15)"
  },
  "canonical_home": null
}
tokens/index.json
{
  "id": "cjk-thin-type-system",
  "kind": "fonts",
  "title": "CJK Thin Type System · 中文细体排版语言",
  "version": "1.0.0",
  "summary": "暗色单页站的中文极细排版语言:字号 4 档 · 字重 2 档(另附「越大越细」阶梯)· 字距 3 档 · 行高 3 档 · 文字影 2 档。约法 = 组件只继承,不再自己写 font-size / font-weight / letter-spacing / line-height / text-shadow。",
  "split": "与 cjk-typography 分工:那条管「用哪些字」(字族与回退栈),本条管「用几档、多细、多宽、多高、几层影」。本包不下发字族。",
  "axes": [
    { "id": "scale", "count": 4, "file": "tokens/scale.json", "what": "字号档(giant / display / title / body)" },
    { "id": "weights", "count": 2, "file": "tokens/weights.json", "what": "字重档(text 200 / mark 600)+ 越大越细配对" },
    { "id": "tracking", "count": 3, "file": "tokens/tracking.json", "what": "字距档(0 / .02em / .12em)" },
    { "id": "leading", "count": 3, "file": "tokens/leading.json", "what": "行高档(1.4 / 1.35 / 1.6)" },
    { "id": "shadow", "count": 2, "file": "tokens/shadow.json", "what": "文字影档(单层 / 双层扩散)" }
  ],
  "defaults": {
    "scale": "body",
    "weight": "text",
    "tracking": "body",
    "leading": "body",
    "shadow": "text"
  },
  "floors": {
    "cjk_px": 12,
    "thin_weight_px": 17,
    "leading": 1.35,
    "display_shadow_px": 28
  },
  "family_pack": "cjk-typography",
  "rules": [
    "组件只继承,不再各自写 font-size / font-weight / letter-spacing / line-height / text-shadow —— 同一字号挂多字重、各组件一套行高,正是「字体乱」的根因",
    "行高与文字影绑字号档,不绑组件",
    "响应式写进 clamp 的中段,上限用绝对单位;禁用 vw 外推上限",
    "同一字号只挂一种字重",
    "中文禁斜体;禁 border-bottom 当前下划线",
    "正文中文不加字距;.02em / .12em 只给标题与微标签"
  ],
  "trap": "按钮不吃继承:button / input 用 UA 默认字(回落无文字影的正文字形),必须 button,input,select,textarea{font:inherit;letter-spacing:inherit;text-shadow:inherit}"
}
tokens/scale.json
{
  "id": "scale",
  "unit": "px",
  "floor_px": 12,
  "note": "字号 4 档。地板 12px 是任何中文文字的最小值(微标签),细体档的更高地板见 weights.json。clamp 中段用 vw 做响应式、上限一律绝对单位。",
  "tiers": [
    {
      "id": "giant",
      "role": "字标 —— 全站唯一允许挂显示字族的元素",
      "css": "clamp(44px, 8.2vw, 122px)",
      "min_px": 44,
      "max_px": 122,
      "weight": "mark",
      "leading": "display",
      "shadow": "display",
      "note": "源卡未给字标字距档:保持 0,不额外加"
    },
    {
      "id": "display",
      "role": "标语 / 邮箱 —— 全站最大正文",
      "css": "clamp(28px, 3.2vw, 44px)",
      "min_px": 28,
      "max_px": 44,
      "weight": "text",
      "leading": "display",
      "shadow": "display",
      "note": "≥28px 才允许第二层扩散影"
    },
    {
      "id": "title",
      "role": "区块标题 / 卡片标题",
      "css": "clamp(20px, 2vw, 22px)",
      "min_px": 20,
      "max_px": 22,
      "weight": "text",
      "tracking": "title",
      "leading": "title",
      "shadow": "text"
    },
    {
      "id": "body",
      "role": "正文 / 界面 / 微标签",
      "css": "17px",
      "min_px": 17,
      "max_px": 17,
      "weight": "text",
      "tracking": "body",
      "leading": "body",
      "shadow": "text",
      "note": "细体正文的地板就是 17px,不许更小;微标签要再小必须把字重抬到 400(见 weights.json)"
    }
  ]
}
tokens/weights.json
{
  "id": "weights",
  "pair": {
    "text": 200,
    "mark": 600
  },
  "tiers": [
    { "id": "text", "value": 200, "what": "正文档:细体,只准挂在 ≥17px" },
    { "id": "mark", "value": 600, "what": "字标 / 强调档:显示字族与小块强调" }
  ],
  "floor_px": 12,
  "thin_min_px": 17,
  "ladder": [
    { "weight": 200, "min_px": 17, "max_px": null, "note": "细体只能挂大字号" },
    { "weight": 300, "min_px": 14, "max_px": 16, "note": "中号:再小开始「笔画溶解」" },
    { "weight": 400, "min_px": 12, "max_px": 13, "note": "微标签:12px 地板,不许更小,也不许更细" }
  ],
  "ladder_note": "区间上界由相邻档与 12px 地板推出;源卡只给了下界(200 ≥17 / 300 ≥14)与「400 只准 ≤12px」两条。",
  "rule": "越大越细:200 只准 ≥17px;300 只准 ≥14px;400 只准 ≤12px。全站最小档 ≥17px 时,唯一合法正文档就是 200。",
  "anti_pattern": "同一字号挂两种字重(200 与 300 并存)是最常见的「乱」,合并到一档。"
}
tokens/tracking.json
{
  "id": "tracking",
  "unit": "em",
  "tiers": [
    { "id": "body", "value": "0", "what": "正文 / 界面:中文不加字距(--ls-0)" },
    { "id": "title", "value": "0.02em", "what": "标题:轻微开一点,给中文标题透气" },
    { "id": "label", "value": "0.12em", "what": "微标签 / eyebrow:拉丁小字与全大写标签" }
  ],
  "cjk_rules": [
    "中文正文不加字距(加字距会把中文行切成碎块)",
    ".02em / .12em 只用于标题与微标签,不下放到正文",
    "中文禁两端对齐(text-align:justify 会用字距变化去填行,中文行宽因此抖动)"
  ],
  "anti_pattern": "给中文正文加 letter-spacing 冒充「高级感」;一页里出现第四档字距值。"
}
tokens/leading.json
{
  "id": "leading",
  "unit": "ratio",
  "floor": 1.35,
  "tiers": [
    { "id": "display", "value": 1.4, "what": "大字标语 / 字标" },
    { "id": "title", "value": 1.35, "what": "区块标题(全站最小行高,不许再压)" },
    { "id": "body", "value": 1.6, "what": "正文 / 界面:中文正文的舒适区" }
  ],
  "rule": "行高绑字号档,不绑组件 —— 11 种行高的根因就是每个组件自己写 1.55 / 1.6 / 1.65 / 1.7 / 1.78 / 1.9。",
  "anti_pattern": "用行高当间距工具(要留白加 margin,不要拉 line-height);正文行高压到 1.35 以下。"
}
tokens/shadow.json
{
  "id": "shadow",
  "tiers": [
    {
      "id": "text",
      "css": "0 1px 2px rgba(0,0,0,.9)",
      "layers": 1,
      "min_px": 0,
      "what": "正文 / 界面 / 标题:发丝笔画只配单层影"
    },
    {
      "id": "display",
      "css": "0 3px 12px rgba(0,0,0,.55), 0 10px 44px rgba(0,0,0,.7)",
      "layers": 2,
      "min_px": 28,
      "what": "≥28px 的标语 / 字标:第二层扩散影只给大字号"
    }
  ],
  "rule": "细体只配单层影;第二层扩散影只给 ≥28px。发丝笔画 + 双层影 = 糊成一团,肉眼看就是「字体变粗了」。",
  "anti_pattern": "给 17px 正文加第二层扩散影;用彩色 glows 当文字影(暗色站上会直接吃掉笔画对比)。"
}
docs/usage.md
# usage · cjk-thin-type-system 配对规则

> 核心主张:排版声明**只继承、只挂档**。组件里出现裸的 `font-size` / `line-height` / `letter-spacing` / `text-shadow`,就是这套语言破口的开始。

## 1 谁配谁(元素 → 档)

| 元素 | 字号档 | 字重 | 字距 | 行高 | 文字影 |
|---|---|---|---|---|---|
| 字标(全站唯一显示字族) | `giant` | `mark` 600 | 0 | 1.4 | `display`(双层,≥28px) |
| 标语 / 邮箱 | `display` | `text` 200 | 0 | 1.4 | `display` |
| 区块标题 / 卡片标题 | `title` | `text` 200 | `.02em` | 1.35 | `text` |
| 正文 / 界面 | `body` | `text` 200 | 0 | 1.6 | `text` |
| 微标签 / eyebrow(12px 级) | 自定义小档 | 400 | `.12em` | ≥1.35 | `text` |

- 字族不在本包:去 `cjk-typography` 取(`body-sans` 回退栈 / `sys-console` 系统栈 / 免费细体三选)。
- 12px 级的微标签是**唯一**允许低于 17px 的中文,且必须把字重抬到 400 —— 细体小字会「笔画溶解」。

## 2 何时用细体(判据)

1. **暗底 + 大字号**才成立:细体靠白字在暗底上的发光量显出笔画;17px 以下、或亮底,笔画直接变灰。
2. 一页最多两档细体字号(标语 + 正文);第三档开始观感从「高级」滑向「没力气」。
3. 需要力量感、数据密度、亮底长文时不要用:分别走粗体档、系统栈、纸媒正文档。
4. 已有站点先普查后收敛,不要凭感觉改单个元素:`audit` 探针(见 §4)先输出「字重分布 / 字号分布 / 组合表」三张表。

## 3 硬约束(改坏一条即不算这套语言)

| 约束 | 值 | 反例 |
|---|---|---|
| 中文最小字号 | 12px | `font-size:11px` 的角标 |
| 细体最小字号 | 17px | 15px 挂 200 字重 |
| 最小行高 | 1.35 | 正文行高 1.2 |
| 第二层影 | ≥28px 才准 | 给 17px 正文加扩散影 |
| `vw` | 只在 `clamp()` 中段 | `font-size:5vw`(无上限) |
| 斜体 | 中文禁 | `font-style:italic` 套中文 |
| 下划线 | 禁 `border-bottom` 当下划线 | 中文正文 `border-bottom:1px solid` |

**越大越细**(字重阶梯):`200 ≥17px` · `300 14–16px` · `400 12–13px`。同一字号只挂一种字重;全站最小档 ≥17px 时,唯一合法正文档就是 200。

## 4 审计探针(能跑起来,不是建议)

`scripts/assert_tokens.py` 把探针做成了可失败的检查,四条都是硬断言:

1. **字号地板**:`preview/` 下所有 CSS / HTML 的 `font-size` 声明,纯 `px` 值不得 < 12px;`clamp()` 的最小值同样不得 < 12px。
2. **最小行高**:`line-height` 无单位值不得 < 1.35。
3. **`vw` 外推**:`font-size` 里出现 `vw` 时,只允许出现在 `clamp()` 的中段,且上限必须是绝对单位;裸 `font-size:Xvw` 直接判失败。
4. **中文禁斜体**:样式表里不得出现 `font-style:italic`。

ps:探针只扫打包产物(`preview/`),把它接到你的项目上时,把它指向项目的样式表即可。

浏览器里做同样的普查(源卡自带的 DOM 探针,按「叶子级文字节点」取样,避免父级重复计数):

```js
const rows = [];
document.querySelectorAll('body *').forEach(el => {
  const t = (el.textContent || '').trim();
  if (!t) return;
  if ([...el.children].some(c => (c.textContent || '').trim())) return;
  const cs = getComputedStyle(el);
  rows.push({ size: +parseFloat(cs.fontSize).toFixed(1), w: cs.fontWeight, ls: cs.letterSpacing, lh: cs.lineHeight, sh: cs.textShadow, fam: cs.fontFamily.split(',')[0] });
});
const g = new Map();
for (const r of rows) { const k = [r.fam, r.size, r.w, r.ls, r.lh, r.sh].join('|'); const e = g.get(k) || { ...r, n: 0 }; e.n++; g.set(k, e); }
console.log('组合数', g.size, '| 字号集合', [...new Set(rows.map(r => r.size))].sort((a, b) => b - a),
            '| 字重集合', [...new Set(rows.map(r => r.w))].sort(), '| 影种类', new Set(rows.map(r => r.sh)).size);
```

## 5 反模式

- 用行高当间距工具(要留白加 `margin`,不要拉 `line-height`)。
- 同一字号挂两种字重(200 与 300 并存)—— 最常见的「乱」。
- 给中文正文加 `letter-spacing` 冒充「高级感」;一页出现第四档字距值。
- 按断点逐组件改 `font-size`(会留下 18 / 20 / 24 / 26px 等散值);响应式一律写进 `clamp()` 中段。
- 给 17px 正文加第二层扩散影,或用彩色 glow 当文字影。
- 拉丁显示字族套中文元素(会静默回落宋体,笔画与字面全变)。
- 用 `text-align: justify` 排中文(字距被拿来填空,行宽抖动)。
- 把字标字族下放给普通标题;字标是全站唯一允许出现显示字族的元素。

## 6 实测样本(源卡)

某暗底单页站 2026-10-31 全站普查:**151 个文字元素 / 21 种样式组合**(9 种字距 / 11 种行高 / 11 种文字影 / 字族里混进 Arial),按本包收敛后:组合 21 → 9、排版声明 223 → 31 条、字族 3 → 2、行高 11 → 3、文字影 11 → 2。

## 7 取用

```bash
python <sai-assets>/scripts/apply.py cjk-thin-type-system --to src/tokens
```

消费后在项目 `design-lock.json` 记 `assets[]`:`pack=cjk-thin-type-system`、`version`、`sha`(见 `docs/USAGE-INTEGRATION.md`)。
SKILL.md
---
name: cjk-thin-type-system
description: Apply a thin-weight CJK type language (4 size tiers, 3 tracking tiers, 3 line-height tiers, 2 text-shadow tiers, 12px floor, bigger-is-thinner weight ladder) to dark single-page sites, portfolios and personal sites. Use when CJK type looks inconsistent — one size carrying several weights, every component writing its own line-height/letter-spacing/shadow — or when a site must read "thin, clean, one language".
---

# cjk-thin-type-system

一套中文**细体**排版语言:字号 4 档 / 字重 2 档 / 字距 3 档 / 行高 3 档 / 文字影 2 档。组件只继承,不再自己写 `font-size` / `font-weight` / `letter-spacing` / `line-height` / `text-shadow`。

## When to use

- 中文 / 日文**暗底**单页站、作品集、个人站,要求「细、干净、一套语言」
- 站点已经「字体乱」:同一字号挂多字重、每个组件一套行高 / 字距 / 阴影(先跑审计探针普查,再按本包收敛)
- 需要把响应式字号写成不可漂移的档位(而不是各断点改 `font-size`)

## When not to use

- 明亮纸媒长文 / 正文阅读 → `cjk-typography` 的 `article` 衬线栈
- 控制台、地图 HUD、内网工具 → 系统栈(`cjk-typography` 的 `sys-console` 档)
- 需要粗体力量感的营销落地页、霓虹 / 赛博风
- 只要概念、不管字族:`cjk-typography`

## Default

默认整站 = `body` 档:`17px` / 字重 `200` / 字距 `0` / 行高 `1.6` / 单层影 `0 1px 2px rgba(0,0,0,.9)`。

## Files

| path | use |
|------|-----|
| `tokens/index.json` | 五个轴的目录、默认档、地板与硬规则 |
| `tokens/scale.json` | 字号 4 档(giant / display / title / body)+ 每档绑定的字重 / 字距 / 行高 / 影 |
| `tokens/weights.json` | 字重 2 档(text 200 / mark 600)+「越大越细」配对阶梯 |
| `tokens/tracking.json` | 字距 3 档 + 中文禁字距 / 禁两端对齐 |
| `tokens/leading.json` | 行高 3 档(1.4 / 1.35 / 1.6)+ 最小行高 1.35 |
| `tokens/shadow.json` | 文字影 2 档 + 第二层只给 ≥28px |
| `docs/usage.md` | **配对规则 + 地板 + 反模式 + 审计探针** |
| `preview/index.html` | 活预览(档位阶梯 + 字号 / 行高 / 影对照) |
| `scripts/assert_tokens.py` | 断言:产物齐备 · 档位自洽 · 字号地板 · 最小行高 · 禁 `vw` 外推 |

## Agent apply steps

1. 读 `tokens/index.json`,把 `floors` 与 `rules` 当硬约束;再按页面元素读 `tokens/scale.json` 取档。
2. 字族去 `cjk-typography` 取(本包不下发字族);本包只决定档位。
3. 把六个 token 文件里的值抄进项目的 `:root`(变量名自定),**不要**在组件里写裸数值。
4. 组件的排版声明只允许「继承」或「挂某个档」两种写法;确需换档,挂 `scale.json` 里的档 id。
5. 收尾:改完跑 `python <pack>/scripts/assert_tokens.py`;若项目里有预览,顺手把审计探针那三条(字号地板 / 最小行高 / `vw` 外推)对本项目样式表跑一遍。

## Hard rules

- **地板 12px**:任何中文文字不许小于 12px;12px 起必须 400 字重。
- **越大越细**:200 只准 ≥17px;300 只准 ≥14px;400 只准 ≤12px。同一字号只挂一种字重。
- **最小行高 1.35**,且行高绑字号档、不绑组件。
- **细体只配单层影**;第二层扩散影只给 ≥28px。
- **禁用 `vw` 外推上限**:`clamp()` 的中段可以用 `vw`,上限必须是绝对单位。
- **CJK 禁斜体**、**禁 `border-bottom` 当前下划线**(中文没有斜体字形,合成斜体会糊;下划线会切掉下伸笔画)。
- 中文正文不加字距,禁两端对齐。
- 按钮不吃继承:`button,input,select,textarea{font:inherit;letter-spacing:inherit;text-shadow:inherit}`。
- 拉丁显示字族只给纯拉丁字标;给中文元素会**静默回落**宋体。

← 回目录