DECENT · 写给开发者的 UI 设计小书

像样 你不缺审美,你缺的是出处。
让一个开发,一个人,也能做出像样的界面。

28 章 · 七卷 28 个互动 Demo 10 台真引擎 关掉 78 个自由度 M 键量这本书自己
难看是可以量化的。

你写完一个界面,感觉「不太对」,但说不出哪里不对。于是你换了个蓝色,加了点阴影,把圆角从 8 改成 12——还是不对。

问题从来不在那个蓝色。把一份真实业务代码那样的界面声明丢进计数器:六个界面、44 个元素,里面有 18 个不同的字号24 种间距12 种圆角25 个颜色——一共 110 个当时随手定的数

你能说出 13.5sp 和 14sp 的分别吗?用户也不能。但他能感觉到这一屏「有点脏」。

设计师不是每次都选得比你好,是他们不每次都选。他们先把值定下来,之后每写一个界面,只从那几个值里取。这本书做的就是这件事:把界面上的自由度一个个关掉,关到最后只剩 34 个。

而你有一样设计师没有的东西:你能把规则写成代码。他们靠眼睛和纪律维持一致,你可以靠类型系统。

这本书自己就是范例

既然讲设计,这本书必须能被检查。所以它把自己的构造公开了:

  • 正文浮在一块白画板上,宽屏时左边有一条真的刻度尺,8 一小格、48 一大格;
  • 随便翻到哪一章,M,整页浮出红线标注——每两个区块之间的间距是多少、落没落在 8 的格子上、每段文字的字号行高、文字和背景的真实对比度是几比几;
  • 这些数字是当场从 DOM 量的getBoundingClientRect + getComputedStyle,再把颜色喂进 WCAG 公式),不是写死的。你可以拿这本书自己做一次 UI 审查。

还有一件事:这本书的卷色不是挑的。它们是书里那台 OKLCH 引擎生成的——同一个亮度 L = 0.52、同一个目标彩度 C = 0.125,只有色相在动。其中黄和青塞不下 0.125,被夹到了各自的上限,因为 sRGB 的色域不是个球。这件事本身就是第 13 章的教材。

第七卷是补卷,取了同一个 L 但把彩度压到 0.02——全书唯一一个近乎无彩的卷色。它讲的就是表面。

九台真引擎

这本书里没有一个数是我拍脑袋写的。所有对比度、色阶、行盒、聚类、模糊、弹簧、Fitts 全部现场算,验证器会把正文里手写的数字和引擎的返回值逐个对一遍。其中两台值得单独说:

HCT 引擎与 Google 官方库逐位相同

第 15 章那台调色板引擎,是 Material 3 取色空间 HCT 的完整实现(CAM16 色貌模型 + CIE L* 亮度 + 色域边界求解器)。它和 Google 的 material-color-utilities 对过答案:

  • 6000 组随机 (H, C, T) → sRGB,6000 个逐位相同
  • 8 个种子色 × 5 条色阶 × 24 个色调,共 960 格全中
  • 而且里面那两个关键矩阵不是抄 Google 源码里的常数,是从 M16 × sRGB→XYZ 现算的——算出来和它对到小数点后 15 位。
字体度量直接读字体文件

第 10 章讲「设计稿上对不上的那几个像素」,用的不是博客上抄来的数,是 scripts/probe-fonts.mjs 直接解析字体文件二进制的 head / hhea / OS/2 / hmtx 表。Roboto 取的是 Android Studio 里 layoutlib 用的那一份——也就是 Android 预览真正拿来排版的文件本身。

于是「16sp 的 Roboto 默认行高 18.75px,开着 includeFontPadding 会变成 21.10px,上面多 1.922 下面多 0.430」这句话里的每个数,都能追到那个文件的某几个字节。

和《Refactoring UI》的关系

那本书(Adam Wathan & Steve Schoger,2018)是「写给开发者的设计书」这个品类的原型,这本书从它那儿拿了不少东西,都在正文里标了出处:标签是最后手段(第 2 章)、从太多留白开始往回收(第 5 章)、别在彩色背景上用灰字(第 16 章)、无障碍不等于难看(第 14 章)、一切都有它该有的尺寸(第 27 章)、阴影是两层的(第 25 章)、少用线(第 26 章)、先做灰度(第 28 章)。

有两处这本书没有跟它走,也照实写在了正文里:

  • 它主张放弃模块化音阶、手挑一套字号。它的理由(音阶取整后会撞车)是对的,第 9 章那个 Demo 就把撞车算了出来。但这本书的处理是「音阶定初值 → 手工圆整 → 锁死」,而不是一开始就凭直觉挑——因为凭直觉挑正是那 18 个字号的来源。
  • 它说「扔掉 hex,改用 HSL」。方向对,但那把尺子本身是歪的:hsl(60 100% 50%) 的黄和 hsl(240 100% 50%) 的蓝,白底对比度差 8 倍。2018 年 OKLCH 还没进 CSS,现在有了——见第 13 章。

目录

卷 II · 距离SPACE
间距不是装饰,是语法——它在声明谁跟谁是一伙的。这一卷是全书性价比最高的一卷。
  1. 05间距在说「这两个是不是一伙的」▸ 真单链聚类
  2. 06为什么是 8▸ 网格对齐检查器
  3. 07对齐:眼睛比参考线挑剔▸ 真光学质心
  4. 08留白到底归谁管▸ Modifier 顺序
卷 III · 字TYPE
你界面上 90% 的像素是文字,而你从没量过它。这一卷把字号、行高、行长全部变成算式。
  1. 09从 18 个字号收到 5 个▸ 模块化音阶
  2. 10设计稿上对不上的那几个像素▸ 真字体度量
  3. 11一行到底放多少字▸ 行长尺
  4. 12一种字体的五种用法▸ 层级配方
卷 V · 手HAND
动效和触摸——界面上唯一会「回话」的部分。也是最容易做成噪音的部分。
  1. 17动效不是装饰,是因果▸ 有无对照
  2. 18那条曲线:贝塞尔与弹簧▸ 真求解器
  3. 19手指不是鼠标▸ Fitts 尺
  4. 20一个按钮有多少种样子▸ 状态矩阵
卷 VII · 表面SURFACE补卷
主线刻意绕开的第三个维度:阴影、边框、图像,以及一个反直觉的工作法。
  1. 25光从上面来▸ 真高度引擎
  2. 26少用线▸ 分隔手段对照
  3. 27图不是装饰,它有固有尺寸▸ 压字对比度
  4. 28先做灰度,颜色最后加▸ 灰度优先

怎么读这本书

如果你只有一个晚上

第 1 章(立总账)、第 5 章(间距即语法)、第 14 章(对比度)、第 24 章(检查表)。这四章覆盖了「让界面立刻不难看」的绝大部分,而且全部可以当场检查。

如果你想按顺序读

就按顺序。前六卷是有依赖的:卷 I 给词汇,卷 II 到卷 V 一个维度一个维度地关自由度,卷 VI 把它们装进代码。每章末尾有一张「本章关掉的自由度」的账,主线 24 章加起来是 67 条——那就是第 24 章那张检查表的来源。

卷 VII 是补卷(第 25–28 章),讲主线刻意绕开的第三个维度:阴影、边框、图像,以及一个反直觉的工作法「先做灰度」。它不是主线的一部分,但如果你已经把前 24 章跑通了,那四章会让界面再往上抬一档。加上它,全书一共 78 条。

如果你只想抄一套能用的值

直接跳第 21 章,那里有一份可以粘进 MaterialTheme 的完整 token。但请至少回头看一眼第 13 章——否则你不会知道为什么不能用 HSL 调那套颜色。

一句话

这本书不教你培养审美。它教你把每一个数变得有出处——然后你会发现,「像样」是这件事的副产品。


从第 1 章开始 ▶