8

准备工作

字符 - Character

字母、数字、汉字、符号等,是一种抽象实体。

字形 - Glyph

单个「字符」的具体表达,一个字可有多个不同的字形。

Glyph

原则上 Unicode 中只对,而非字形编码。

字型 - Font

印刷行业中,指某一整套具有同样样式和尺码的字形,如一整套中易宋体 5 号字、一整套 9 磅 Helvetica Neue粗体字。

Helvetica Neue的字重

字体 - Typeface

若干个「字型」在若干个尺寸上的集合。

字体与字族

随着计算机字体 (computer font) 的普及,可缩放的矢量字体的出现使得「字型」与「字体」的界限逐渐模糊,现今这两个概念在数字排印领域越来越多地被当做同义词使用。

「书体」- 宋体、仿宋体、黑体等…

例如 Windows 自带的「宋体」实为「中易宋体」。

Fonts分类

西文字体

基础术语

基础术语

基础术语

分类

名称 描述 举例
serif(衬线体) 衬线体有爪形的衬线并且笔划粗细有变化 Centaur,Garamond,Caslon,Baskerville,Didot,Bodoni
sans-serif(无衬线体) 完全抛弃装饰衬线,笔画粗细对比小,x高度较高 Helvetica,Franklin Gothic,Futura,Gill Sans,Optima,Univers,Myriad,Avenir
cursive(手写体) 一般具有连笔(joining strokes)或者其它除斜体字体外的手写特征 Comic Sans MS
fantasy(幻想体) 主要是装饰性的,但仍然具有字符表现(与不表现字符的Pi或者Picture字体相反) Bodoni Ornaments
monospace(等宽体) 所有字形都具有相等的固定宽度 Menlo

这里面,我们经常用到的是serif体和sans-serif

serif

sans-serif

Serif与Sans-Serif

Serif强调字母笔画的开始及结束,因此前后连续性强,易读性高。

Sans Serif则较醒目,但在行文阅读的情況下,Sans-Serif 容易造成字母辨认的困扰,常会有来回重读及上下行错乱的情形。在小字体的场合,通常Sans-SerifSerif更清晰。

适用用途

通常文章的內文、正文使用的是易读性较佳的 Serif 字体,这可增加易读性,而且长时间阅读下因为会以word为单位来阅读,较不容易疲倦。

而标题、表格內用字则采用较醒目的Sans Serif字体,它需要显著、醒目,但不必长时间盯著这些字来阅读。

像宣传品、海报类,为求醒目,它的短篇的段落也会采用Sans-Serif字体。但在书籍、报刊杂志,正文有相当篇幅的情形下,则应采用Serif字体来减轻读者阅读上的负担。在Web设计及浏览器设置中也应遵循此原则为是。

中文字体

中文的书写体系有两种标准,一种是简体中文,一种是繁体中文

简体繁体

分类

名称 描述 举例
宋体(明朝体、明体) 横笔画水平、竖笔画粗壮、拥有华丽但规范字脚的字体 中易宋体(SimSun),新宋体( the Times New Roman)
黑体(哥特体) 结构方正,没有字脚 中易黑体(SimHei),微软雅黑(Microsoft YaHei),思源黑体( Source Han Sans)
楷体 横笔画也可以带角度,柔软且富有弹性的末端,以及符合自然的笔触宽度 Kaiti,方正楷体
仿宋(宋朝体) 横微微倾斜,不会有很大的字脚,横竖笔画的粗细对比也没有宋体那么大 方正仿宋
美术体 美术体是一类极具风格的字体,它们可以包括从稚嫩到厚重到新奇的各类风格 丁丁手绘体

另外,圆体(圆黑体)通常也归入黑体。传统上说的「等线体」以当代视角来看通常是较为幼细的黑体。

中文字体界不少人不主张用「衬线」、「无衬线」来指代宋体和黑体。

宋体

宋体

黑体

黑体

楷体

楷体

仿宋

仿宋

宋体与黑体

宋体,原形为宋代模仿楷书基本笔划(如点、撇、捺),但因应当时以木板作活版印刷,为顺应木的天然纹理,而从楷体左低右高的斜横演变成直横,因为减低损耗而将竖划加粗的印刷用字体。到明代,这种字体逐渐脱离楷书的模样,成为一种成熟的印刷字体。

黑体的发明比较晚,学者对于黑体的历史有很大的争议,但我们可以发现它是二十世纪早期广告印刷品的产物。

适用用途

由于宋体是因为印刷诞生的,所以它更适合报纸和书籍的正文类文字的排版。

由于黑体醒目的特点,常用于标题、导语、标志等等。由于汉字笔划多,小字的黑体清晰度较差,所以一开始主要用于文章标题,但随着制字技术的精进,已有许多适用于内文的黑体字型。

计算机字体分类方式

1. 点阵字体(Bitmap Fonts)

  • 本质上是点阵图片的集合。

  • 渲染极快

  • 显示效果稳定

  • 容易创建

  • 在小字号、多笔画时渲染效果较好

  • 视觉效果较差

  • 不适合缩放

2. 轮廓字体(Outline Font)

  • 是向量图的集合,用 Bézier 曲线描述字形,适合缩放。

  • PostScript 字体

    • Adobe 开发

    • 用三次 Bézier 曲线描述字形。

    • 私有 hinting,价格昂贵

    • 质量高,适合打印专业质量的印刷出版物

    • 又细分为 Type1 / Type3 / CID 等类型

  • TrueType 字体

    • Apple 为对抗 Adobe 的 Type1 与 Microsoft 共同开发

    • 用二次 Bézier 曲线描述字形,渲染较快

    • 可内置点阵字体

    • 在 OS X 和 Windows 中是最常见的字体格式

  • OpenType 字体

    • 源于 Microsoft 独自开发的 TrueType Open

    • 后 Adobe 加入开发,增加对 PostScript 轮廓的支持

    • PostScript flavor / TrueType flavor

    • Adobe 黑体

3. 笔画字体(Stroke-based font)

4. METAFONT

计算机字体区别

如何理解点阵字体和轮廓字体的区别呢,其实它们的表现和图片格式中的png8和png24的的区别很类似,点阵字体都是实色,没有过渡色,边缘锐利,而轮廓字体有过渡色,边缘也比较平滑。很多人把“宋体”(Simsun)当作点阵字体,其实不是,它和“微软雅黑”(Microsoft YaHei)一样,都属于轮廓字体,只不过12px~17px的宋体内置了点阵信息而已。

如下图,前面有两个 T 的是 TrueType 的格式字体,O 开头的是 OpenType 的字体。

OpenType字体中的字形(glyph)、轮廓数据可以在两种格式中任选其一:一个是在glyf表中TrueType格式轮廓,另一个是在CFF表中的CFF(压缩字体格式,Compact Font Format)格式轮廓。CFF轮廓数据是基于PostScript语言Type 2字体格式。表格名CFF长度为四个字符,并且以一个空格字符结尾。

TrueType flavorPostScript flavor

TrueType
OpenType

OS与Fonts

Windows 字体列表

Mac OS X 字体列表

Windows、OS X、Liunx/Unix预装中文字体demo

上面的例子列举了WindowsOS XLiunx/Unix预装字体以及一些版权字体

默认中文字体
Windows OS X Linux/Unix
微软雅黑UI(MicroSoft YaHei UI)Win8+ 苹方-简(PingFangSC)OS X 10.11+ 文泉驿微米黑(WenQuanYi Microhei)
微软雅黑(MicroSoft YaHei )Win Vista+ 黑体-简(Heiti SC)Mac OS X 10.6+ -
中易宋体(SimSun) 华文黑体(STHeiti) -
- 冬青黑体简体中文(Hiragino Sans GB)Mac OS X 10.6+ 非默认 -
Android IOS
思源黑体(Noto Sans CJK SC)Android 5.0+ 苹方-简(PingFangSC)IOS9.0+
Droid Sans Fallback 黑体-简(Heiti SC) iPhone OS 3.0+
- 华文黑体(STHeiti)
默认西文字体
无衬线 衬线 等宽
San Francisco(OS X 10.11+/IOS9.0+ Georgia Menlo
Helvetica(IOS1.0+) / Helvetica Neue(OS X10.10+/IOS 4.0+ Times New Roman Courier
Lucida Grande(OS X) - Monaco
Segoe UI(Win Vista+ - -
Tahoma - -
Verdana - -
Arial - -
Roboto(Android 4.0+ - -
Droid Sans(Android) - -

Fonts的渲染过程

编码

为什么需要编码?

我们知道计算机处理的数据实际上都是二级制的数据,也就是计算机实际上只识别0和1两种状态。发明计算机的过程中人们需要解决的第一个问题就是文字的处理问题,也就是我们如何将文字符号转化为二级制数据,同时我们也需要能够将转化后的二进制数据重新转化为文字符号供我们阅读。前面的过程我们称之为编码,后面的这个过程我们称之为解码。这和电信领域更著名的一套编解码规则莫尔斯码是一个原理。

鉴于各个国家都有自己的字符集和编码方式,为了实现在一份文档中可以正确显示所有类型的字符,Unicode诞生了,伴随着互联网的发展,Unicode字符集和UTF-8编码方式成了互联网通信的标准。

这张 Unicode表分成了很多的 block,把某一类字符放在指定的 block 中,如下图

unicode表

西文字体比如 Helvetica 等,一定会完成拉丁文对应的 block 中的字形,但是他们是不会去做 CJK(中日韩) 的字形。而特殊字符,比如表情符号等,也是有预留位置的,这也是为啥我们经常发现别人发过来的一些东西是方块,因为对方发送的字符在我们自己的机器上并没有相应的字体来显示。

详细编码知识请看 乱码是怎样形成的?

解码

当浏览器收到来自Web服务器的数据后,第一步就是要把它解码成可以阅读的文本,而浏览器判断代码主要是依据以下方法:

  1. Web服务器返回的HTTP头中的Content-Type:text/html;charset=信息,这一般有最高的优先级;

  2. 网页本身metaheader中的Content-Type信息的charset部分,对于HTTP头未指定编码或者本地文件,一般是这么判断;

  3. 假如前两条都没有找到,浏览器菜单里一般允许用户强制指定编码。

  4. 部分浏览器 (比如 Firefox) 可以选择编码自动检测功能,使用基于统计的方法判断未定编码。

分段

编码确定后,网页就被解码成了Unicode字符流,因为我们得到的文本可能是很多种语言混杂的,里面可能有中文、有英文,它们可能要用不同的字体显示;

为了统一处理这些复杂的情况,我们要将文本分为由不同语言组成的小段,在有的文本布局引擎里,这个步骤称为“itemize”。分解后的文本段常被称作“text run”,但是具体划分的规则可能根据不同的引擎有所区别。

不少浏览器还会在这个划分下面,在确定具体使用的字体之后,根据使用字体的不同划分更细的 run,这种 run 可能称作“SimpleTextRun”,每个都会使用和相邻不同的字体,最后把它们逐一交给 shaper 进行排版得到要绘制的字形,这样一来,shaper 的工作就被简化为在确定的语言、确定的字体下排版确定的文本,生成对应的字形和它们应该放置的位置、占用的空间。

Fonts匹配

CSS 2.2 Font matching algorithm
  1. UA 创建(或访问)一个 CSS 2.2 相关属性的字体数据库;

  2. 对每个元素的每个字符,先尝试匹配第一个 font-family 名字;

  3. 找到则尝试匹配剩余属性 (font-style, font-variant, …);

  4. 如果 (1) 没有完全匹配的字体,或 (2) 字体匹配但相应字形缺失,则尝试匹配下一个 font-family

  5. 如果 font-family 无法匹配,UA 分配默认字体;

  6. 如果该字符在 UA 选择的所有字体下均无字形,UA 应选择某个字体中的「missing character」的字形,
    例如「�」。

CSS3字体匹配算法与CSS2.1字体匹配算法的差异:
  • 算法包括font-stretch匹配。

  • 确定了font-style匹配中所有可能的情况。

  • 小型大写字母字体不作为字体匹配过程的一部分进行匹配,它们现在通过字体特性进行处理。

  • 需要Unicode variation selector匹配。

Font属性

font属性使用小demo

小米官网

 font: 14px/1.5 "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei", "Hiragino Sans GB", "Heiti SC", "WenQuanYi Micro Hei", sans-serif;

Font-family属性

Font匹配是通过哪个名称?

name - Naming Table

按 OpenType 规范,字体的名称信息存在 name 表中。

  • Name Records

    • Platform ID

    • Platform-specific encoding ID

    • Language ID

    • Name ID

Name IDs(部分)
ID 含义
1 Font Family name (Family)
2 Font Subfamily name (Style)
4 Full font name (Full)
6 PostScript name
16 Preferred Family
17 Preferred Subfamily
18 Compatible Full (OS X only)
21 WWS Family Name
22 WWS Subfamily Name
宋体 (中易宋体) - Windows Unicode BMP
Name Type Chinese - PRC English - United States
Family 宋体 SimSun
Style Regular Regular
Full 宋体 SimSun
PostScript name 宋体 SimSun
Adobe 黑体 - Windows Unicode BMP
Name Type Chinese - PRC English - United States
Family Adobe 黑体 Std R Adobe Heiti Std R
Style Regular Regular
Full - AdobeHeitiStd-Regular
Preferred Family Adobe 黑体 Std Adobe Heiti Std
Preferred Subfamily R R
PostScript name AdobeHeitiStd-Regular AdobeHeitiStd-Regular

Windows 的字体预览会采用你目前的系统语言对应的 Preferred Family 作为命名,如果此项缺失则会用系统语言 Family、英语 Preferred Family、英语 Family。

对浏览器来说不同浏览器的处理策略是不一样的,比如 IE9 和 FF4 支持按照 Preferred Family 选字而 Chrome 只按照 Family(Opentype 规范里的 [name] 表项目)搜索。

Fallback

fallback是字体匹配算法的重要机制,我们看一下下面的例子:

font-family: 'Helvetica Neue', 'Helvetica', 'Microsoft Yahei', sans-serif;

Fallback

这个 fallback 的规则可以总结为

(hasFont && isInUnicodeTable) ? 'Current Font' : 'Next Font'

就这样一直找匹配的字体,直到系统默认,所以一般都把系统默认的5类字体放到 font-family 定义的最后来写。

CSS规范里只简单的说执行“system font fallback”。但这个过程在不同的系统不同的浏览器下可能很不一样,比如:

  • OS相关机制

    • Linux下一般通过fontconfig去根据语言、风格等参数来选择fallback,但不同浏览器的实现还可能有区别。

    • Windows下则一般会使用系统的Font Linking机制,根据注册表内的FontSubstitutes信息来寻找。

    • OS X是按照字体后备列表进行fallback。
      os x fallback

  • 浏览器配置

    • WebKit settings 中可设定各个 generic family 的默认值。

    • Firefox访问 about:config 后筛选出的 font 相关项中包含不同语言下 generic families 的默认值。

    • Webkit会使用font-family列表的第一个字体和这段文字所属的语言来寻找fallback字体,像Times这样的serif字体对应的中文fallback字体,在Mac OS X下是华文宋体(STSong)。

    • Firefox则会根据sans-serif这样的通用font-family和对应的语言匹配到设置中针对对应语言的默认字体,比如在MAC OS X 默认的中文非衬线字体是华文黑体(STHeiti)(新版本 OS X是苹方-简)。

  • charset、lang 属性、font-family值

因为在这里不同的浏览器可能有不同的行为,所以建议在CSS中应写明对应平台所使用的字体。

具体的字体选择还有一些不太容易注意的细节,也是各个浏览器差异比较大的一点,可能会出现这样一些问题:

  • 是否支持用字体的PostScript name选择:如STHeiti的Light版本又称作STXihei,或者是否能用full name 选择:有的浏览器不能正确地将CSS里对字体的font-weight或者font-style等要求映射到特定的字体上,尤其是在字体使用了非标准的style明明的情况下。

  • 是否支持按 Localized name选择:比如能不能用“宋体”来代表“Simsun”。以Mac OS X下的浏览器为例,Firefox支持这样的写法,但基于Webkit的浏览器一般不支持,这样的问题CSS规范没有限定,所以无论哪种情况都是允许的。

总的说来,如果要保证最大限度的兼容性,在 CSS 书写的时候应该尽可能选择明确、不容易出错的写法,尽量少隐式地让浏览器自己确定 (be explict instead of implict),虽然隐式写法通常比较简洁,但除非你 100% 确定想支持的浏览器在你想支持的平台下都能支持这个写法,否则还是不应该轻易用。

其它注意事项请参看:font-family 没有设定中文字体时,汉字应该怎么显示?

渲染

当字体确定以后,就可以将文本,字体等等参数一起交给具体的排版引擎,生成字形和位置,然后根据不同的平台调用不同的字体rasertizer将自行转换成最后显示在屏幕上的图案,一般浏览器都会选择平台原生的resterizer

排版引擎

不同浏览器有着不同的渲染引擎。Mac OS X 用户使用 CoreText 渲染引擎,Windows7 和 Windows Vista 用户使用 DirectWrite.aspx) 或 GDI ,而 Windows XP 则使用 GDI。

GDI 分为 GDI Grayscale 和 GDI ClearType 。前者为灰阶渲染 API,后者是亚像素渲染 API。由于 GDI ClearType 并未对字体进行垂直方向的平滑,因此当字体较大时会出现边缘不平滑的情况。为了弥补 GDI ClearType 的不足,MS实现了 DirectWrite API,它在 GDI ClearType 的基础上增加了垂直方向的平滑。

对比图片来看看它们之间的区别,其中上图为FacitWeb字体,下图为 Minion Pro字体。

Core Text 渲染引擎

Core Text 渲染引擎

DirectWrite渲染引擎

DirectWrite渲染引擎

GDI渲染引擎,开启ClearType

GDI渲染引擎,开启ClearType

GDI渲染引擎,标准抗锯齿(Standard antialiasing)

GDI渲染引擎,标准抗锯齿(Standard antialiasing)

GDI渲染引擎,无抗锯齿(no antialiasing)

GDI渲染引擎,无抗锯齿(no antialiasing)

使用同一颜色,感官上的颜色深浅为:黑白渲染> grayscale > sub-pixel。

iOS 和 Mac 的渲染引擎一样,但采用的是灰度渲染,默认情况下亚像素抗锯齿是关闭的,但可以通知设置开启。

由于渲染策略的不同,字母a在不同的浏览器和 OS 下的渲染表现也不同。第一个是理想模型的a,第二个是灰阶渲染的a,第三个是亚像素渲染,第四个是黑白渲染。

浏览器

常用字体在浏览器中的渲染情况

浏览器支持表

注:从 chrome52 开始,google 停止对于老的操作系统的支持,包括 windows xp 和 windows vist a停止了 GDI 的字体渲染,从而只支持 DirectWrite。

光栅化

当确定了编码、字体类型、排版引擎、浏览器后,就要进行光栅化了,光栅化是将文字从一个向量表示(比如一个TrueType)转化到光栅或者位图表示的过程。在这个过程中往往涉及到一些抗锯齿技术使得屏幕上的字体更加顺滑易读,这也经常会涉及到“字体微调(font hinting)”技术。

建议

根据以上总结我们可以看出,不同系统预装的字体不同,不同浏览器的默认字体也不同,而且还有渲染引擎的差异。所以,要想达到比较好的显示效果,需要设置好font-family

  1. 首先确定要选择字体的元素应该使用的字体风格,比如是衬线字体、非衬线字体还是 cursivefantasy 之类的。

  2. 优先声明英文字体,比如 Mac OS X 下有 Helvetica 也有 Arial,但 Helvetica (可能) 效果更好,Windows 下则一般只有 Arial,那么写 Helvetica, Arial 就比 Arial, Helvetica 或者只有 Arial 更好。

    • 绝大部分中文字体都包含英文字母和数字,但是大多数中文字体中的英文和数字部分都不是特别漂亮,所以建议对英文字体先进行声明。

  3. 然后列出中文字体,Windows下,Microsoft Yahei是最常用的字体,Mac如果安装了Office,系统也会安装Microsoft Yahei字体,可Mac下Microsoft Yahei显示效果不是太好,所以一般把Mac的字体放在前面,Microsoft Yahei放在后面,最后还可以跟上Linux下的WenQuanYi Micro Hei

  4. 最后还应该放上对应的generic family,比如sans-serif或者serif

  5. 尽量用字体的基本名称 (比如 English locale 下显示的),而不要用本地化过的名称。除非特殊情况 (Windows 下“某些”浏览器在特定编码下只能支持本地化的字体名称)。Mac OS X 下字体名称可以用 Font Book 查到 (菜单 Preview -> Show Font Info),Windows 下字体信息在微软的网站可以得到,Linux/X11 下可以使用 fc-list 命令查到。

  6. 字体名称中包含空格时记得用引号扩起来,比如"WenQuanYi Micro Hei"

  7. 文档开头最好指明语言,比如<html lang="en-us">。但是对于简体中文来说,我们不应该使用lang=zh-cn,但是为了浏览器的兼容性,还继续使用。详细参见网页头部的声明应该是用 lang="zh" 还是 lang="zh-cn"?

基于以上考虑,我们先来看看最安全的的font-family是什么样的:

html lang=zh-CN//为了兼容性,暂时先这么写
charset=utf-8
font-family:arial,sans-serif;

扩充一下,加上常用的字体fallback:

PC端

font-family: -apple-system,BlinkMacSystemFont,"San Francisco","Helvetica Neue",Helvetica,Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","WenQuanYi Microhei",sans-serif;

移动端


   font-family:  "\5FAE\8F6F\96C5\9ED1", Helvetica;//手机腾讯
   font-family:'STHeiti','Microsoft YaHei',Helvetica,Arial,sans-serif;//手机网易

-apple-system用于调用系统默认UI字体,并且会根据font-weight声明选择恰当的变体。system将来有可能成为标准-apple为过渡阶段的厂商前缀。

BlinkMacSystemFont:为 macOS Chrome 应用系统 UI 字体,与上面等同。

一般移动端不需要设置中文字体,\5FAE\8F6F\96C5\9ED1是微软雅黑的Unicode码,中文测试用。

相关参考

给自己的字体课(一)

百用不厌明星字体

中文字体新手指南

中文字体分类除了黑体和宋体之外还有哪些?

讨论:中文字体及呈现需求

从《中文排版需求》开始

CSS font-family常见中文字体对应的英文名称

各个平台下相对比较好的 Web 英文字体分别是什么?

网页字体设置你了解吗?

移动开发规范概述

网页中字体的那些事

Web 字体的选择和运用

Python字符编码的学习

浏览器如何渲染文本

网站字体渲染过程

有关字体的小小迷思

Type rendering: operating systems

如何保证网页的字体在各平台都尽量显示为最高质量的黑体?

在 Web 内容中使用系统字体

Using UI System Fonts In Web Design: A Quick Practical Guide

Using the System Font in Web Content

对于 CSS 的「font-family」,浏览器是通过字体的哪个名称进行匹配的?

最佳 Web 中文默认字体

是否有一种软件能够对不同语言的文字指定不同的字体?

CSS Font Stack


人丑就要多读书_
197 声望17 粉丝