衬线、字重与可变字体AI 主写
字体不只是“长得好不好看”。在前端和设计里,字体至少会影响三件事:阅读体验、品牌气质、以及页面渲染是否稳定。
基础概念
先分清几组最容易混在一起的概念:字体风格、字体家族、字重和字体文件。
衬线体和无衬线体
字体最常见的分类是衬线体和无衬线体。
图中红色部分就是 serif,也就是衬线。图片来源:Wikimedia Commons。
衬线体是笔画末端带装饰的字体,比如宋体、Times New Roman。它通常更有书籍感、传统感,适合长文、正式出版物、标题排版。
无衬线体是笔画末端没有明显装饰的字体,比如黑体、苹方、思源黑体、阿里巴巴普惠体。它更干净、现代,屏幕显示更常见,适合网页、App、后台系统和数据看板。
简单判断:
- 宋体、Times New Roman:衬线体。
- 黑体、苹方、思源黑体、阿里巴巴普惠体:无衬线体。
字体家族、字重和字体文件
我们平时说“一个字体”,其实可能包含多个字体文件。比如一个字体家族里可能有:
- Regular:常规字重。
- Medium:中等字重。
- Semibold:半粗。
- Bold:粗体。
在 CSS 里,常见写法是:
.title {
font-family: "Some Font";
font-weight: 500;
}
但这句话是否真的会切到 Medium,取决于字体文件是怎么注册的。
可变字体与静态字体
字体文件的组织方式,大体可以分成可变字体和静态字体。这里的关键问题是:一个文件能不能覆盖连续变化的字重或字宽。
可变字体
可变字体是一种把多个字重、字宽、倾斜等变化能力放进一个字体文件里的字体格式。
自制示意图。这张图把可变字体的几个常见轴画出来了:
optical size、weight、width。同一个字母a可以沿着不同轴连续变化。相关概念可参考 Variable fonts on the web。
如果一个字体是可变字体,通常可以用一个文件连续调节字重:
@font-face {
font-family: "Some Variable Font";
src: url("./SomeVariableFont.woff2") format("woff2");
font-weight: 300 800;
}
.title {
font-family: "Some Variable Font";
font-weight: 642;
}
这里的 642 是可以成立的,因为可变字体内部支持连续变化。
静态字体
不可变字体也可以叫静态字体。它通常是多个固定文件:
SomeFont-Regular.woff2
SomeFont-Medium.woff2
SomeFont-Bold.woff2
这种字体不能靠一个文件连续变化。浏览器只能在已注册的固定字重之间选择,或者在缺少目标字重时做“伪加粗”。
从网页加载角度看,两者的差异也很直观:
自制示意图。静态字体往往需要多个字体文件来覆盖不同字重和样式;可变字体可以把更多变化能力收进一个文件里。相关概念可参考 Variable font - Wikipedia。
阿里巴巴普惠体是哪一种
阿里巴巴普惠体通常是不可变字体,也就是静态字体家族。它提供多个固定字重文件,比如 Regular、Medium、Semibold、Bold 等。
所以它不是“一个文件里连续调节所有字重”的可变字体。要让 font-weight 正确工作,需要把不同字重文件正确注册给浏览器。
前端里的 font-weight 坑
到前端实现里,真正容易出问题的是:font-weight 看起来是字重语义,但它必须配合正确的 @font-face 注册才可靠。
font-weight 不一定等于切到对应字体文件
这是最容易踩坑的地方。
如果只加载了 Regular 文件:
@font-face {
font-family: "PuHuiTi-Regular";
src: url("./AlibabaPuHuiTi-3-45-Light.woff2") format("woff2");
font-weight: 400;
}
然后写:
.title {
font-family: "PuHuiTi-Regular";
font-weight: 500;
}
浏览器并不会凭空找到 Medium 文件。它可能会:
- 继续使用 Regular。
- 对 Regular 做伪加粗。
- 根据浏览器和系统策略做近似匹配。
这就是为什么 computed style 里看到 font-weight: 500,视觉上却不像真正的 Medium。
更推荐的注册方式
更理想的方式是:同一个字体家族下注册多个字重。
@font-face {
font-family: "Alibaba PuHuiTi";
src: url("./AlibabaPuHuiTi-3-45-Light.woff2") format("woff2");
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: "Alibaba PuHuiTi";
src: url("./AlibabaPuHuiTi-3-65-Medium.woff2") format("woff2");
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "Alibaba PuHuiTi";
src: url("./AlibabaPuHuiTi-3-75-SemiBold.woff2") format("woff2");
font-weight: 600;
font-style: normal;
}
这样组件里就可以只写语义:
.body {
font-family: "Alibaba PuHuiTi", "Helvetica Neue", Arial, sans-serif;
font-weight: 400;
}
.title {
font-family: "Alibaba PuHuiTi", "Helvetica Neue", Arial, sans-serif;
font-weight: 500;
}
浏览器会在同一个 font-family 下,根据 font-weight 自动选择对应文件。
不太推荐的注册方式
有些项目会把不同字重注册成不同字体族:
@font-face {
font-family: "PuHuiTi-Regular";
src: url("./AlibabaPuHuiTi-3-45-Light.woff2") format("woff2");
font-weight: 400;
}
@font-face {
font-family: "PuHuiTi-Medium";
src: url("./AlibabaPuHuiTi-3-65-Medium.woff2") format("woff2");
font-weight: 500;
}
这时如果想用 Medium,就必须同时切换 font-family:
.title {
font-family: "PuHuiTi-Medium", "PuHuiTi-Regular", "Helvetica Neue", Arial, sans-serif;
font-weight: 500;
}
这种写法不是不能用,但它会让组件层知道太多字体文件细节。长期看,最好还是收敛成同一个字体家族,靠 font-weight 表达字重语义。
验证字体是否真的生效
验证字体时,不要只看:
getComputedStyle(el).fontWeight;
还要看:
getComputedStyle(el).fontFamily;
如果视觉要求很严格,还需要实际截图或肉眼对比。因为 computed style 只能告诉你 CSS 结果,不一定能直接告诉你浏览器最终用了哪个字体文件。
总结
可变字体是“一个字体文件里有连续变化能力”;不可变字体是“多个固定字重文件组成一个字体家族”。
阿里巴巴普惠体通常属于不可变字体。使用它时,font-weight: 500 是否真的等于 Medium,取决于项目有没有把 Medium 文件正确注册到同一个 font-family 下。
参考资料
- Serif - Wikipedia:解释 serif 是附着在笔画末端的小线条或笔画。
- Sans-serif - Wikipedia:解释 sans-serif 是没有 serif 的字形分类,也提到它常用于屏幕显示。
- Variable font - Wikipedia:解释可变字体可以在一个字体文件里存储连续范围的设计变体。
- Variable fonts on the web:可变字体在网页中的使用说明。