一种字体的五种用法
上一章你已经有了一套字号。但层级不止靠字号——你手上其实有五个旋钮,而新手和熟手的区别就是:熟手每次只拧一两个。
五个旋钮
要让一段文字比另一段「更重要」,你能动的东西一共这么几样:
关键在于:它们是可以互相替代的,不是叠加的。
把开关一个个打开。你会发现开到第三个之后,标题并没有变得更清楚,只是变得更吵。
层级的作用是让人一眼分出主次,不是让人感受到你调了很多参数。
正文和图注的差别,可以只是深浅。
标题和正文的差别,可以只是字号。
按钮上的文字和正文的差别,可以只是字重。
第 4 章那个「花」,本质就是每个层级都动用了全部五个旋钮,于是所有层级都在用最大音量说话。
降级不是做小做丑
第 2 章说过「一屏只能有一个主动作,其余降级」。这里说清楚降级该怎么做。
把次要按钮做小、做灰、加个细边框。
- 触摸目标跟着缩水(第 19 章)
- 灰到看不清,用户以为是禁用
- 细边框在深色底上会消失
尺寸不变,只降视觉重量。
- 高度、字号、内边距全部保持一致
- 只去掉填充色(Filled → Outlined → Text)
- 对比度仍然守 4.5:1,绝不用「禁用灰」
Material 的按钮族就是照这条设计的:Button、OutlinedButton、TextButton 三者高度完全一样,差别只在填充。
这是很常见的一次撞车:次要按钮用了浅灰,禁用按钮也用了浅灰,于是用户分不清「这个不重要」和「这个不能点」。
可查的判据:禁用态的对比度应该低于 4.5:1(它就该看不清),而次要动作必须高于 4.5:1。两者在数值上是分开的区间,不该重叠。
图标比文字重
一个容易被忽略的失衡来源:同样大小的图标,视觉重量远大于文字。
原因在第 3 章讲过——视觉权重 ≈ 面积 × 亮度差。一个 24px 的实心图标是一整块墨,而 24px 的文字大部分面积是空白(笔画只占其中一小部分)。
- 图标和它旁边的文字不要用同一个颜色——图标用低一档的(比如文字用
onSurface,图标用onSurfaceVariant)。 - 装饰性图标(列表项前面那种)压得更狠,它们不该和内容抢注意力。
- 唯一的例外是图标本身就是主角时:空态的大插图、成功页的对勾。
反过来也成立:如果你有一排图标按钮,其中一个要突出,给它加填充背景比把它调深更有效——因为填充直接增加了面积。
字距
第四个旋钮最少人用,但它是「专业感」的一大来源。规律只有两条:
字号越大,字距要越紧。字形是按正文尺寸设计的,放大之后字母之间的空隙会跟着放大,看起来就散。所以大标题要给一点负字距。
全大写和小字号标签要放开。大写字母全是等高的方块,挤在一起难辨认;小字号同理。
Material 3 的 token 就是这个规律:displayLarge(57sp)是 −0.25sp,而 labelSmall(11sp)是 +0.5sp。
| 用在哪 | 字号 | 字距 |
|---|---|---|
| 首页主标题 | 42px | −0.022 em |
| 章首标题 | 33px | −0.015 em |
| 小标题 | 21px | −0.008 em |
| 正文 | 17px | 0 |
| 全大写标签 | 任意 | +0.06 em |
中文不要加字距。汉字本身就是等宽方块,加了字距会散架。上面这套只对拉丁文和数字生效——所以如果你的标题是中英混排,负字距会让英文部分变紧而中文部分看起来被挤压,需要单独处理。
视觉层级 ≠ 文档层级
最后一条,来自《Refactoring UI》,纠正一个开发者特别容易犯的直觉错误:
你的语义结构(哪个是 h1、哪个是 h2)和视觉层级是两套独立的东西。
典型例子:一个博客文章页,语义上「网站名」可能是 h1、「文章标题」是 h2。但视觉上文章标题必须是最大的——因为用户点进来是看文章的,不是看网站名的。
另一个:设置页里,「分组标题」(账号、通知、隐私)语义上是标题,但视觉上应该比条目文字更小更淡——因为条目才是用户要点的东西,分组标题只是路标。
这条在 Compose 里尤其容易犯,因为 Typography 的名字带着强烈的语义暗示:headlineLarge 听起来就该给标题用。
// ✗ 按语义选 style
Text("设置", style = MaterialTheme.typography.headlineMedium)
Text("通知", style = MaterialTheme.typography.titleMedium) // 分组标题
Text("允许推送", style = MaterialTheme.typography.bodyLarge) // 真正要点的东西
// ✓ 按「你想让人先看哪个」选 style
Text("设置", style = MaterialTheme.typography.headlineMedium)
Text(
"通知", // 分组标题:路标,压轻
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.primary // 用颜色而不是字号来标识它
)
Text("允许推送", style = MaterialTheme.typography.bodyLarge) // 保持最重
选 style 的时候,问的不该是「这在文档结构里是第几级」,而是「我想让人第几个看到它」。
卷 III 收尾
字这一卷四章,可以压成一张表:
到这里为止,你的界面已经关掉了 34 个自由度,而我们还一个颜色都没碰。下一卷开始碰——那是全书唯一一处「凭感觉」会必然出错的地方。
- 「怎么区分这两级」——五个旋钮里挑一到两个,不是全上。字重最多三档。
- 「次要按钮做多小多灰」——尺寸一律不变,只去填充色。对比度仍守 4.5:1,禁用态才允许低于它。
- 「用哪个 typography」——按「想让人第几个看到」选,不按文档层级选。图标比同尺寸文字重,主动压一档颜色。