chapter[0] · design-system.md

本书的设计系统

约束不是创造力的敌人,而是它的脚手架。 查尔斯·伊姆斯(Charles Eames),设计师

在写下第一个字之前,这本书先写了一份 style.css。这不是工程洁癖,而是本书要教的第一课:美不是灵感的随机输出,而是一组被严格执行的决定。你将在第八章看到,工业界把这组决定叫作设计系统(Design System)。这一章公开本书自己的设计系统——它只有五种颜色、三种字体、一个 8px 网格,以及十来个组件。读完后,你在本书任何一页看到的任何视觉细节,都可以在这里找到出处。

程序员视角

设计系统之于界面,相当于类型系统之于代码:它把"什么是允许的"提前声明,把无穷的选择空间压缩成少数合法值。一个页面用了第六种颜色,等同于一次类型错误——也许能跑,但迟早出事。

0.1色彩:五个语义角色

本书的色彩系统借自中国传统印刷:纸、墨、朱砂、黛青、金。关键不在于这五个色值本身,而在于每种颜色绑定一个语义角色——颜色因此变得可预测:看到朱砂红,你就知道这是重点或章号;看到黛青,那一定可以点击。

#FAF7F0
全书底色
#211D19
正文文字
朱砂#C2452D
强调 · 章号
黛青#2D5A6B
链接 · 代码
#B98A2F
高亮 · 练习

注意底色不是纯白 #FFFFFF,文字也不是纯黑 #000000。纯白配纯黑的对比度高达 21:1,长时间阅读会刺眼;暖白配暖黑(约 14:1)既远超无障碍标准(WCAG 要求正文 ≥ 4.5:1),又模拟了纸张的柔和。第一个可以立刻带走的技巧:永远不要在界面里使用纯黑文字配纯白背景。

0.2文字:三个声部

本书只用三种字体,像三种乐器,各司其职:

--serif 正文思源宋体 —— 庄重、适合长文阅读
--sans 标签思源黑体 —— 克制、用于图注与导航
--mono 代码JetBrains Mono — precise & honest

字号不是随手定的,而是来自一个公比 1.25 的模数字阶(modular scale):13 → 15 → 18 → 22 → 28 → 36 → 46 → 58。就像音阶里的音符,相邻字号之间存在固定的比例关系,整个页面因此有了"和声"。正文 18px、行高 2 倍,是为中文长文阅读调校的——汉字是方块字,比拉丁字母需要更宽的行距才能呼吸。

程序员视角

模数字阶就是字号的"等比数列生成器":fontSize(n) = base × ratio^n。Tailwind 的 text-sm/base/lg/xl… 就是一个预计算好的字阶。当你不知道标题该用多大时,不要微调像素,去字阶里取下一级。

0.3空间:8px 网格与版心

本书所有间距都是 8 的倍数:8、16、24、32、40、48、64、96。这条规则消灭了"这里到底空 13px 还是 17px"的纠结——当所有间距来自同一个节拍,页面自然显得整齐,哪怕你说不出为什么。

正文栏宽 720px,约等于每行 36 个汉字。这是排版学里的行长(measure):太长,眼睛换行时会迷路;太短,视线跳动太频繁。西文的经验值是每行 45–75 字符,中文约 25–40 字。图版允许"破栏"到 960px——重要的画作值得更大的舞台,这种宽窄变化本身也是一种节奏。

0.4组件:本书的 UI 词汇表

以下组件构成了本书全部的表达手段。组件少而精确,胜过多而含糊。

组件用途设计意图
figure.art 图版真实艺术品 + 图注 + "怎么看"每张图必须带鉴赏指引,拒绝装饰性配图
.callout.dev 程序员视角把美学概念翻译成工程语言黛青色 = 工程的声音
.callout.practice 鉴赏练习章末动手训练金色 = 值得花时间的高亮
.callout.key 核心概念必须记住的结论朱砂 = 最高优先级
.compare 对比并置好坏方案并排鉴赏力的最快训练法是对比
.principle 原则块编号的设计原则等宽数字编号,可被引用

三种标注框的实物演示:

核心概念

朱砂色块只用于全书最重要的结论。一章最多出现两三次——强调的东西一多,就什么都没强调。

鉴赏练习

金色块是留给你的作业。本书的每个练习都可以在 15 分钟内完成,但效果取决于你是否真的动手。

0.5这套系统背后的四个决定

01

像书,不像网页

居中单栏、衬线正文、大量留白、没有侧边栏和悬浮按钮。阅读长文时,一切非内容元素都是噪音。

02

每个视觉决定可解释

问任何一处"为什么是这样",答案要么在本章,要么在 style.css 的注释里。不可解释的装饰已被删除。

03

约束优先于灵感

五种颜色、三种字体、一个网格。后面十六章无论内容如何变化,都不允许突破这套词汇。

04

图版是一等公民

这是一本鉴赏书,画作享受最大版面、最重投影和强制的"怎么看"指引。文字为图让路。

0.6这套系统的边界:自我批判与无障碍

一套设计系统是否成熟,不看它有多自洽,而看它知不知道自己的边界。每个系统都是为某个目标优化的,因此必然在别的目标上让步——说不出自己"为什么而优化、以什么为代价"的系统,只是还没遇到打脸的场景。为了示范这种诚实,这本书拿自己开刀,先做一次它最该被审的项:对比度(第九章 9.6 会正式讲)。下面是本书全部文字用色在纸色上的真实对比度账本:

在纸色 #FAF7F0 上 · 数值为近似对比度 · WCAG 正文要求 ≥ 4.5:1 墨 · 正文示例文字 ≈13:1 ✓正文——稳。 墨淡 · 次要正文示例 ≈7:1 ✓图注/次要段——达标。 黛青 · 链接示例文字 ≈6:1 ✓链接/代码——达标。 朱砂 · 强调与章号 ≈4.4:1 ⚠踩线——只用于大字/粗体,不作正文。 金 · 高亮示例文字 ≈3:1 ✗不达标——只做着重底纹,绝不作正文色。 墨微 · 标注示例文字 ≈2.6:1 ✗不达标——仅用于页码/元信息等可丢失内容。 诚实的结论:本书 6 个文字色里有 2 个(金、墨微)和 1 个踩线(朱砂)达不到正文标准—— 这不是 bug,是有意识的边界:它们被严格限制在"丢了也不影响理解"的非正文角色里。说得出口,才叫守住边界。
图 0-2 · 本书调色板的对比度自审 · 本书绘制 一套系统给自己开的诚实账单 直接用眼睛验证那两行 ✗:金色和墨微的"示例文字"是不是真的比上面几行费劲?这就是 9.6 要消灭的东西。关键不在"本书有没有低对比的颜色"——有;而在它有没有把这些颜色关进笼子里:金只做高亮底纹、墨微只标页码、朱砂只上大字。一个色值达不达标是技术问题,一个系统知不知道该把它用在哪,才是品味问题。

对比度只是其中一项。这套"像书不像网页"的系统,还有几处坦白的代价:① 为沉浸阅读优化,就牺牲了查阅——没有持久导航、没有搜索、一路长滚动,你想跳到"第九章数据密度那段"并不方便(一个工具型文档绝不该这么设计,但一本书可以)。② 固定 720px 版心把中文长文行长锁得很舒服,代价是它对"边读边对照代码"这类双栏需求毫无帮助。③ 朱砂同时担任"强调"和"链接悬停"两个角色,存在轻微的语义张力——严格说一个颜色一个语义,这里为了克制总色数破了一点例。每一条都是真实的取舍,写出来不是为了道歉,是为了证明:这套系统的每个边界都是被看见、被选择的,而不是被忽略的。

程序员视角

给你自己的设计系统做同样的体检,两步即可:① 跑一遍对比度——把你的文字色 × 背景色组合扔进任何对比度检查器(或 axe),像上面这样列出账本,然后给每个不达标的颜色明确写下"它只许出现在哪里"。② 写下一句"优化目标 / 代价"——"本系统为 ___ 优化,因此在 ___ 上让步"。填不出这句话,说明你还没真正理解自己的系统,只是攒了一堆好看的值。这和给模块写 README 里的"非目标(non-goals)"是同一种成熟度:知道自己不做什么、不擅长什么,比罗列功能更能体现设计的清醒。

鉴赏练习 0

两道题。① 语义一致性:翻回目录页,找出朱砂色出现的所有位置,验证它们是否真的都是"强调/链接"语义;再看你最常用的一个 App,如果发现同一个红色既表示"删除"又表示"促销",你就完成了人生第一次设计审查。② 边界体检:给你自己项目(或本书)写下那句"为 ___ 优化、在 ___ 上让步",并把主色板跑一遍对比度,列出哪些颜色该被关进"非正文"的笼子。一套说得出自己边界的系统,已经赢过了大多数。