模块化类型比例——每个设计系统字体大小背后的数学原理
为什么任意字体大小看起来略显不协调,以及如何通过一个简单的比例(1.25、1.333、1.618)将一组随机的像素值转化为具有视觉和谐感的排版系统。
你已经盯着原型看了很久。字体大小是 14px, 16px, 18px, 24px, 32px, 48px。看起来没有问题,的确如此——但某种感觉却略显奇怪。不同大小之间的跳跃并不均匀。标题离副标题太近了。小标签与正文文字之间显得脱节。你一直选择那些看起来圆整且合理的数字,却在疑惑为什么结果会显得有些随意。它确实是随意的。这就是问题所在。
事实是,人类对大小差异的感知大致是对数关系。我们不会把16px和32px之间的差异感知为“翻倍”——我们只会感知为一个步骤。为了创建在视觉上 比例一致的排版,你字体大小之间的间隔需要遵循比例关系,而不是等差数列。这就是模块化比例(modular scale)的理念。
模块化比例实际上是什么
模块化比例是一组通过不断将一个基础值乘以固定比例而构建出来的数字序列。公式如下:
size = base × ratio^n
其中 n n 是步骤数(0为基准值,正值为更大,负值为更小)。以 16px 为基准值, 1.25 (大三度)为基础,得到:
- 16 × 1.25^-2 = 10.24px
- 16 × 1.25^-1 = 12.8px
- 16 × 1.25^0 = 16px(基准值)
- 16 × 1.25^1 = 20px
- 16 × 1.25^2 = 25px
- 16 × 1.25^3 = 31.25px
- 16 × 1.25^4 = 39.06px
每一步的增量都恰好是前一步的25%倍。视觉上的跳跃感觉一致,因为它们 是 一致的——呈几何关系。与 14, 16, 18, 24, 32, 48相比,其中的跳跃 +2, +2, +6, +8, +16。看似圆整的间距实际上极其不一致。
命名比例(以及何时使用)
这些名称源自西方音乐音程,它们遵循相同的数学关系。以下是实际应用的列表:
- 1.067 — 小二度: 非常紧密。步骤几乎无法区分。适用于单个组件内精细的正文间距,不适用于标题层级。
- 1.125 — 大二度: 微妙。适用于需要区分但不夸张的密集界面——例如数据表格、仪表盘。
- 1.25 — 大三度: 大多数网页界面的最佳选择。各级之间的对比足够清晰,能明确阅读层级,同时避免标题显得过大。这是大多数设计系统中最受欢迎的比例。
- 1.333 — 完美四度: 简洁且广泛使用。为标题赋予更多权威感。适用于希望清晰建立排版层级但步骤较少的场景。
- 1.414 — 增强四度(√2): 也是A4纸的长宽比。比完美四度更具冲击力,适用于编辑类内容。
- 1.5 — 完美五度: 各级之间的对比强烈。标题显得宏大且醒目。适用于编辑布局、首页页面,以及任何需要显示文本发出强烈声明的场景。
- 1.618 — 黄金比例: 理论上优美,实践中过于激进。从正文开始向上两步,标题就已经变得巨大。仅适用于仅用于展示的元素,不适用于完整的界面层级。
对于前端开发者构建产品界面,大三度(1.25)或完美四度(1.333)几乎覆盖了所有情况。如果你不确定,从1.25开始。如果层级感觉过于扁平,可以适当增加比例。
模块化比例的实际应用:基于16px的大三度比例
以下是完整的基于大三度比例(比例=1.25,基准=16px)的七步比例示例:
| 步 | 倍率 | px值 | rem值 |
|---|---|---|---|
| xs | 1.25^-2 | 10.24px | 0.64rem |
| 山猫 | 1.25^-1 | 12.8px | 0.8rem |
| base | 1.25^0 | 16px | 1rem |
| lg | 1.25^1 | 20px | 1.25rem |
| xl | 1.25^2 | 25px | 1.5625rem |
| 2xl | 1.25^3 | 31.25px | 1.953rem |
| 3xl | 1.25^4 | 39.06px | 2.441rem |
关于小数部分的说明: 12.8px 且 31.25px 精确保留为rem值完全没问题——浏览器能正确处理亚像素渲染。你无需将其四舍五入到 13px 或 31px ,否则会破坏数学一致性。保持数学的纯净性,让浏览器完成其工作。
CSS自定义属性:你的设计令牌系统
将该比例直接转换为CSS自定义属性。这样你就能在代码库的任何地方轻松使用一个设计令牌系统,并且在之后更改比例时可以轻松替换:
:root {
--font-size-xs: 0.64rem; /* 16 × 1.25^-2 = 10.24px */
--font-size-sm: 0.8rem; /* 16 × 1.25^-1 = 12.8px */
--font-size-base: 1rem; /* base = 16px */
--font-size-lg: 1.25rem; /* 16 × 1.25^1 = 20px */
--font-size-xl: 1.5625rem; /* 16 × 1.25^2 = 25px */
--font-size-2xl: 1.953rem; /* 16 × 1.25^3 = 31.25px */
--font-size-3xl: 2.441rem; /* 16 × 1.25^4 = 39.06px */
}
然后像使用任何设计令牌一样使用它们:
body { font-size: var(--font-size-base); }
small { font-size: var(--font-size-sm); }
h3 { font-size: var(--font-size-xl); }
h2 { font-size: var(--font-size-2xl); }
h1 { font-size: var(--font-size-3xl); }
.label { font-size: var(--font-size-xs); }
与硬编码值相比的优势在于:当设计师决定将比例从1.25改为1.333时,你只需修改一处,七个数值随之更新。每个组件都会自动更新。那些跳过此步骤的设计系统最终会散落在各个组件文件中的五十个字体大小值,每个开发者都会自行添加。开发者与设计令牌之间的关系复杂,但这种做法才是真正有效的。
如果你不想手动计算这些值, 字体模块化比例生成器 可以让你选择基准大小和比例,并立即输出完整的比例序列,同时提供可复制的CSS自定义属性。
何时打破比例规则
比例是工具,不是规则。以下情况可有意打破比例:
展示标题需要单独处理
大多数设计系统使用两种比例:较紧密的比例(1.25或1.333)用于正文和UI组件,更强烈的比例(1.5或1.618)用于展示标题。营销页面上的英雄标题不需要遵循表单内标签的相同层级。Tailwind的默认比例正是如此——在小尺寸时使用较紧密的步长,在展示尺寸时使用更大的跳跃。
流动字体平滑过渡
在移动端视口下,1.5的比例在桌面端表现良好,但在移动设备上会产生标题过小或过大的问题。现代解决方案是 clamp():
h1 {
font-size: clamp(1.953rem, 4vw + 1rem, 2.441rem);
}
该方案保持模块化比例作为最小和最大值的锚点,但根据视口宽度动态调整大小。模块化比例定义了范围; clamp() 负责处理过渡。数学关系保持一致,输出在不同设备尺寸下始终可读。
上下文覆盖是合理的
如果你的 h2 在侧边栏中显得过大,在 1.953rem时,将其缩小到 1.5625rem 是合理的做法。比例为你提供了一个连贯的默认值,而非不可更改的规则。目标是视觉和谐,而非数学纯粹性。当上下文要求时,可以有意识地打破比例——但不要因为随意选择了圆整数字而打破它。
整合应用
选择一个基准大小(通常为16px),选择一个符合所需视觉权重的比例(1.25用于UI,1.333用于更具存在感的元素,1.5用于编辑内容),生成比例序列,并将其写入CSS自定义属性。完成。你的字体大小现在有了数学关系,而非随意的数值,任何查看你代码的设计人员都会立即理解这套系统。
这 字体模块化比例生成器 在IO Tools中,你可以配置基准大小、比例和步数——并直接获得可复制的CSS代码。尝试将比例从1.25调整到1.333,看看标题大小如何迅速变化。这就是值得建立的直觉:理解每个比例 感觉 如何,再将其纳入设计系统。
