Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

3.3 字体技术

字体是文字显示的基础,我们在屏幕上看到的所有文字都是通过字体渲染出来的。对于前端开发、UI设计、排版相关的工作来说,理解字体技术的原理非常重要。

字体的基本概念

什么是字体

字体(Font)是一系列具有相同风格的字符的集合,定义了每个字符的形状(字形)、大小、字重、间距等属性。

字体相关术语

  1. 字形(Glyph):单个字符的形状描述,同一个字符可以有多个字形(比如大小写、不同字重)
  2. 字重(Font Weight):字体的粗细程度,通常用数值表示,100最细,900最粗,常见的400是正常,700是粗体
  3. 字号(Font Size):字体的大小,单位通常是磅(pt)或者像素(px)
  4. 字距(Kerning):两个字符之间的间距调整
  5. 行高(Line Height):两行文字基线之间的距离
  6. 基线(Baseline):文字对齐的基准线,大部分字母的底部都在基线上
  7. serif 衬线字体:笔画末端有装饰性的衬线,比如宋体、Times New Roman,适合印刷阅读
  8. sans-serif 无衬线字体:笔画末端没有衬线,比如黑体、Arial、Roboto,适合屏幕显示
  9. 等宽字体:每个字符的宽度都相同,比如Consolas、Monaco,适合写代码

字号详解

字号是指字体的大小,是排版中最基础也最重要的概念。不同场景下使用的单位和计算方式有所不同。

常见的字号单位

1. 点(Point,pt)

  • 传统印刷业使用的标准单位,1磅大约等于 1/72 英寸
  • 在标准的印刷分辨率(300DPI)下,1pt ≈ 1.333 像素
  • Word、Pages 等排版软件默认使用磅作为单位
  • CSS 也支持 pt 单位,但网页开发不推荐使用

2. 像素(Pixel,px)

  • 屏幕显示使用的单位,1px 对应屏幕上的一个物理像素
  • 是网页开发中最常用的单位,font-size: 16px 表示 16 像素高
  • 在不同 DPI 的屏幕上,实际物理大小不同:
    • 72DPI 屏幕:1px = 1/72 英寸 ≈ 0.3528mm
    • 96DPI 屏幕:1px = 1/96 英寸 ≈ 0.2646mm
    • 视网膜屏(2x):1px = 2 物理像素

3. 相对单位(em、rem、%)

  • em:相对于父元素的字体大小,1em = 当前父元素字体大小
  • rem:相对于根元素(html)的字体大小,在整个页面中比例一致
  • %:和 em 类似,100% 等于父元素字体大小
  • 相对单位适合做响应式设计,让用户可以通过浏览器设置调整整体文字大小

4. 视口单位(vw、vh)

  • vw:1vw = 视口宽度的 1%
  • vh:1vh = 视口高度的 1%
  • 适合需要根据屏幕大小动态调整的大标题

DPI 与字号的关系

DPI(Dots Per Inch,每英寸点数)表示屏幕的物理密度:

  • 传统屏幕:96DPI 或 72DPI
  • 高DPI屏幕(视网膜屏):192DPI 或更高(2x、3x 缩放)

在 CSS 中,px 是“逻辑像素“,不是物理像素:

  • 在 1x 屏幕:1px 逻辑像素 = 1px 物理像素
  • 在 2x 视网膜屏:1px 逻辑像素 = 4px 物理像素(2x2)
  • 字号的逻辑大小不变,只是变得更清晰

字号的黄金比例

排版中常用一些约定俗成的字号比例,让页面更美观:

基准字号:16px(正文)
一级标题:≈ 1.8em ≈ 28.8px
二级标题:≈ 1.5em ≈ 24px
三级标题:≈ 1.25em ≈ 20px
小号文字:≈ 0.875em ≈ 14px
最小字号:≈ 0.75em ≈ 12px

现代网页设计趋势:

  • 正文字号不小于 16px,保证移动端阅读舒适度
  • 大标题可以更大,增强视觉层次感
  • 正文行高通常在 1.5-1.6 倍字号之间

中文字号的编号系统

中文排版传统上使用“号“来表示字号:

字号磅数(pt)像素(px/96DPI)用途
八号5pt~7px极小注释
七号5.5pt~7px注释
小六号6.5pt~9px页脚、注释
六号7.5pt~10px注释、图片说明
小五号9pt~12px正文(报纸)
五号10.5pt~14px正文
小四号12pt~16px正文
四号14pt~19px小标题
小三号15pt~20px小标题
三号16pt~21px一级标题
小二号18pt~24px一级标题
二号22pt~29px大标题
一号26pt~35px大标题
初号36pt~48px封面标题

最佳实践

  1. 网页开发:正文使用 14-16px,移动端不小于 16px 避免缩放
  2. 响应式设计:使用 rem 作为单位,方便整体缩放
  3. 可访问性:不要使用过小的字号,正文字号不小于 14px
  4. 中文排版:因为文字结构比英文复杂,通常需要比英文更大一点的字号才能清晰阅读
  5. 印刷出版:使用 pt 单位,根据印刷尺寸计算合适字号

常见字体格式

1. TrueType(TTF)

  • 由苹果和微软在80年代联合开发的字体格式
  • 是目前最广泛使用的字体格式,Windows和macOS系统都原生支持
  • 使用二次贝塞尔曲线描述字形,缩放不失真
  • 文件扩展名为.ttf

2. OpenType(OTF)

  • 由微软和Adobe联合开发,是TrueType的扩展
  • 支持更高级的排版特性(连字、alternate字符、小型大写字母等)
  • 可以使用TrueType或者PostScript曲线描述字形
  • 文件扩展名为.otf
  • 支持Unicode,能包含大量字符

3. Web开放字体格式(WOFF/WOFF2)

  • 专门为网页设计的字体格式
  • WOFF是TTF/OTF的压缩版本,文件更小,加载更快
  • WOFF2是WOFF的改进版,压缩率比WOFF高30%左右
  • 所有现代浏览器都支持WOFF/WOFF2
  • 文件扩展名为.woff.woff2
  • 是网页字体的首选格式

4. Embedded OpenType(EOT)

  • 微软开发的嵌入式字体格式,只有旧版IE浏览器支持
  • 现在已经基本被淘汰,不需要再使用

5. 可变字体(Variable Fonts)

  • 新一代的字体格式,一个字体文件可以包含多个字重、宽度、甚至斜体的变化
  • 不需要为不同字重加载不同的字体文件,大大减少字体文件大小
  • 可以通过CSS的font-variation-settings属性灵活调整字体样式
  • 现代浏览器都已经支持可变字体,是未来的发展方向

字体渲染原理

字体文件中存储的是字形的矢量描述(贝塞尔曲线),要在屏幕上显示出来,需要经过光栅化过程,把矢量形状转换为像素点阵。

字体渲染流程

  1. 字形解析:从字体文件中读取对应字符的矢量描述
  2. 栅格化:把矢量曲线转换为像素网格上的点阵
  3. 抗锯齿(Anti-aliasing):对边缘的像素进行半透明处理,让文字边缘更平滑
  4. 次像素渲染(Subpixel Rendering):利用LCD屏幕每个像素由RGB三个子像素组成的特性,进一步提升文字清晰度
  5. 显示:把渲染好的文字点阵输出到屏幕上

常见的字体渲染引擎

不同操作系统使用不同的字体渲染引擎,这就是为什么同一个字体在不同系统上显示效果不同的原因:

  1. Windows
    • GDI:旧的渲染引擎,字体比较锐利,但小字号可能会模糊
    • DirectWrite:Windows 7之后引入的新渲染引擎,渲染效果更好,更平滑
  2. macOS / iOS
    • CoreText:苹果系统的渲染引擎,追求字体的打印效果,比较平滑,笔画较粗
  3. Linux
    • FreeType + Fontconfig:开源的渲染引擎,可配置性高,不同发行版效果可能不同

抗锯齿技术

抗锯齿是让文字边缘更平滑的技术,主要有以下几种:

  1. 灰度抗锯齿:根据字形覆盖像素的比例,调整像素的灰度值,让边缘看起来平滑
  2. 次像素抗锯齿(ClearType):利用LCD的RGB三个子像素单独调整亮度,相当于把水平分辨率提高了3倍,文字更清晰。但在OLED屏幕和高DPI屏幕上效果不明显,而且如果显示设备的子像素排列不同,可能会出现彩色边。
  3. 无抗锯齿:不做任何平滑处理,文字边缘有锯齿,但非常锐利,适合极低分辨率的屏幕。

字体渲染的常见问题

  1. 小字号模糊:低DPI屏幕上小字号容易模糊,需要字体做hinting(微调),在小字号下调整字形形状,让显示更清晰
  2. 字体发虚:抗锯齿过渡或者渲染引擎的问题,高DPI屏幕下会好很多
  3. 不同平台显示差异:因为渲染引擎不同,同一个字体在Windows和macOS上显示效果不同,设计时需要考虑这种差异
  4. 字体加载闪烁:网页加载外部字体时,会出现FOIT(Flash Of Invisible Text,文字先不可见后显示)或者FOUT(Flash Of Unstyled Text,先显示系统字体后替换为自定义字体)的问题

网页字体最佳实践

网页开发中使用自定义字体已经非常普遍,这里分享一些最佳实践:

1. 优先使用系统字体

如果不是必须使用特殊字体,优先使用系统自带的字体,加载最快,显示效果最好:

/* 系统字体栈 */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, "Noto Sans", sans-serif,
             "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",
             "Noto Color Emoji";

系统字体不需要下载,渲染效果最好,是大多数场景的首选。

2. 选择合适的字体格式

  • 现代浏览器优先使用WOFF2,其次是WOFF,最后是TTF/OTF
  • 不需要再支持EOT格式,除非需要兼容IE8及以下
  • 示例:
@font-face {
  font-family: 'MyFont';
  src: url('myfont.woff2') format('woff2'),
       url('myfont.woff') format('woff'),
       url('myfont.ttf') format('truetype');
}

3. 优化字体加载

  • 字体子集化:只包含需要用到的字符,比如中文网页如果只需要常用汉字,可以把字体文件从几MB缩小到几十KB
  • 预加载字体:使用<link rel="preload">提前加载关键字体
  • 使用font-display控制加载行为
    • font-display: swap:先显示系统字体,字体加载完成后替换,避免文字不可见
    • font-display: fallback:短时间内加载不出来就用系统字体,加载完成后替换
    • font-display: optional:如果字体不能很快加载完成,就一直用系统字体
  • 合理缓存字体:设置较长的Cache-Control头,让浏览器缓存字体文件

4. 避免常见问题

  • 不要使用太多不同的字体,每个额外的字体都需要额外的HTTP请求和下载
  • 注意字体的版权问题,不要随意使用商业字体
  • 考虑 fallback 字体,即使自定义字体加载失败,也能有合适的替代字体显示
  • 对于中文网页,大字体文件建议使用字体拆分或者云字体服务

字体的版权问题

字体是有版权的,和软件、音乐、图片一样,使用商用字体需要获得授权:

  • 免费商用字体:思源黑体、思源宋体、站酷系列字体、阿里巴巴普惠体等,可以免费商用
  • 商业字体:微软雅黑、苹方、方正系列等,需要购买授权才能商用
  • 注意:很多系统自带的字体虽然你可以在自己电脑上用,但不代表你可以嵌入到网页、App或者商业设计中使用,需要确认版权

开发相关技巧

  1. 字体加载检测:可以使用document.fontsAPI检测字体是否加载完成
  2. 可变字体的使用:如果使用可变字体,可以大大减少字体文件数量,同时提供更灵活的样式控制
  3. 不同平台字体适配:针对不同操作系统选择合适的字体,保证显示效果一致
  4. 无障碍考虑:保证字号足够大,行高合适,对比度足够,方便阅读

思考问题

  1. 为什么同一个字体在Windows和macOS上显示效果不同?
  2. 网页中使用自定义字体有哪些性能问题?如何优化?
  3. WOFF2格式比TTF格式有什么优势?为什么网页推荐使用WOFF2?
  4. 什么是可变字体?它相比传统字体有什么好处?