原则上 Unicode 中只对字,而非字形编码。css
随着计算机字体 (computer font) 的普及,可缩放的矢量字体的出现使得「字型」与「字体」的界限逐渐模糊,现今这两个概念在数字排印领域愈来愈多地被当作同义词使用。html
例如 Windows 自带的「宋体」实为「中易宋体」。python
名称 | 描述 | 举例 |
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
体git
Serif
强调字母笔画的开始及结束,所以先后连续性强,易读性高。github
Sans Serif
则较醒目,但在行文阅读的情況下,Sans-Serif
容易形成字母辨认的困扰,常会有来回重读及上下行错乱的情形。在小字体的场合,一般Sans-Serif
比Serif
更清晰。web
一般文章的內文、正文使用的是易读性较佳的 Serif
字体,这可增长易读性,并且长时间阅读下由于会以word为单位来阅读,较不容易疲倦。算法
而标题、表格內用字则采用较醒目的Sans Serif
字体,它须要显著、醒目,但没必要长时间盯著这些字来阅读。chrome
像宣传品、海报类,为求醒目,它的短篇的段落也会采用Sans-Serif
字体。但在书籍、报刊杂志,正文有至关篇幅的情形下,则应采用Serif
字体来减轻读者阅读上的负担。在Web设计及浏览器设置中也应遵循此原则为是。数据库
中文的书写体系有两种标准,一种是简体中文,一种是繁体中文windows
名称 | 描述 | 举例 |
宋体(明朝体、明体) | 横笔画水平、竖笔画粗壮、拥有华丽但规范字脚的字体 | 中易宋体(SimSun),新宋体( the Times New Roman) |
黑体(哥特体) | 结构方正,没有字脚 | 中易黑体(SimHei),微软雅黑(Microsoft YaHei),思源黑体( Source Han Sans) |
楷体 | 横笔画也能够带角度,柔软且富有弹性的末端,以及符合天然的笔触宽度 | Kaiti,方正楷体 |
仿宋(宋朝体) | 横微微倾斜,不会有很大的字脚,横竖笔画的粗细对比也没有宋体那么大 | 方正仿宋 |
美术体 | 美术体是一类极具风格的字体,它们能够包括从稚嫩到厚重到新奇的各种风格 | 丁丁手绘体 |
另外,圆体(圆黑体)一般也纳入黑体。传统上说的「等线体」以当代视角来看一般是较为幼细的黑体。
中文字体界很多人不主张用「衬线」、「无衬线」来指代宋体和黑体。
宋体,原形为宋代模仿楷书基本笔划(如点、撇、捺),但因应当时以木板做活版印刷,为顺应木的自然纹理,而从楷体左低右高的斜横演变成直横,由于减低损耗而将竖划加粗的印刷用字体。到明代,这种字体逐渐脱离楷书的模样,成为一种成熟的印刷字体。
黑体的发明比较晚,学者对于黑体的历史有很大的争议,但咱们能够发现它是二十世纪早期广告印刷品的产物。
因为宋体是由于印刷诞生的,因此它更适合报纸和书籍的正文类文字的排版。
因为黑体醒目的特色,经常使用于标题、导语、标志等等。因为汉字笔划多,小字的黑体清晰度较差,因此一开始主要用于文章标题,但随着制字技术的精进,已有许多适用于内文的黑体字型。
本质上是点阵图片的集合。
渲染极快
显示效果稳定
容易建立
在小字号、多笔画时渲染效果较好
视觉效果较差
不适合缩放
是向量图的集合,用 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 黑体
如何理解点阵字体和轮廓字体的区别呢,其实它们的表现和图片格式中的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
长度为四个字符,而且以一个空格字符结尾。
Windows、OS X、Liunx/Unix预装中文字体demo
上面的例子列举了Windows
、OS X
、Liunx/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) | - | - |
为何须要编码?
咱们知道计算机处理的数据实际上都是二级制的数据,也就是计算机实际上只识别0和1两种状态。发明计算机的过程当中人们须要解决的第一个问题就是文字的处理问题,也就是咱们如何将文字符号转化为二级制数据,同时咱们也须要可以将转化后的二进制数据从新转化为文字符号供咱们阅读。前面的过程咱们称之为编码,后面的这个过程咱们称之为解码。这和电信领域更著名的一套编解码规则莫尔斯码是一个原理。
鉴于各个国家都有本身的字符集和编码方式,为了实如今一份文档中能够正确显示全部类型的字符,Unicode诞生了,伴随着互联网的发展,Unicode字符集和UTF-8编码方式成了互联网通讯的标准。
这张 Unicode表分红了不少的 block,把某一类字符放在指定的 block 中,以下图
西文字体好比 Helvetica 等,必定会完成拉丁文对应的 block 中的字形,可是他们是不会去作 CJK(中日韩) 的字形。而特殊字符,好比表情符号等,也是有预留位置的,这也是为啥咱们常常发现别人发过来的一些东西是方块,由于对方发送的字符在咱们本身的机器上并无相应的字体来显示。
详细编码知识请看 乱码是怎样造成的?
当浏览器收到来自Web服务器的数据后,第一步就是要把它解码成能够阅读的文本,而浏览器判断代码主要是依据如下方法:
Web服务器返回的HTTP头中的Content-Type:text/html;charset=
信息,这通常有最高的优先级;
网页自己meta
header中的Content-Type
信息的charset
部分,对于HTTP头未指定编码或者本地文件,通常是这么判断;
假如前两条都没有找到,浏览器菜单里通常容许用户强制指定编码。
部分浏览器 (好比 Firefox) 能够选择编码自动检测功能,使用基于统计的方法判断未定编码。
编码肯定后,网页就被解码成了Unicode字符流,由于咱们获得的文本多是不少种语言混杂的,里面可能有中文、有英文,它们可能要用不一样的字体显示;
为了统一处理这些复杂的状况,咱们要将文本分为由不一样语言组成的小段,在有的文本布局引擎里,这个步骤称为“itemize”。分解后的文本段常被称做“text run”,可是具体划分的规则可能根据不一样的引擎有所区别。
很多浏览器还会在这个划分下面,在肯定具体使用的字体以后,根据使用字体的不一样划分更细的 run,这种 run 可能称做“SimpleTextRun”,每一个都会使用和相邻不一样的字体,最后把它们逐一交给 shaper 进行排版获得要绘制的字形,这样一来,shaper 的工做就被简化为在肯定的语言、肯定的字体下排版肯定的文本,生成对应的字形和它们应该放置的位置、占用的空间。
UA 建立(或访问)一个 CSS 2.2 相关属性的字体数据库;
对每一个元素的每一个字符,先尝试匹配第一个 font-family
名字;
找到则尝试匹配剩余属性 (font-style
, font-variant
, …);
若是 (1) 没有彻底匹配的字体,或 (2) 字体匹配但相应字形缺失,则尝试匹配下一个 font-family
;
若是 font-family
没法匹配,UA 分配默认字体;
若是该字符在 UA 选择的全部字体下均无字形,UA 应选择某个字体中的「missing character」的字形,
例如「�」。
算法包括font-stretch匹配。
肯定了font-style匹配中全部可能的状况。
小型大写字母字体不做为字体匹配过程的一部分进行匹配,它们如今经过字体特性进行处理。
须要Unicode variation selector匹配。
小米官网
font: 14px/1.5 "Helvetica Neue", Helvetica, Arial, "Microsoft Yahei", "Hiragino Sans GB", "Heiti SC", "WenQuanYi Micro Hei", sans-serif;
name - Naming Table
按 OpenType 规范,字体的名称信息存在 name 表中。
Name Records
Platform ID
Platform-specific encoding ID
Language ID
Name ID
…
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 |
Name Type | Chinese - PRC | English - United States |
Family | 宋体 | SimSun |
Style | Regular | Regular |
Full | 宋体 | SimSun |
PostScript name | 宋体 | SimSun |
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是字体匹配算法的重要机制,咱们看一下下面的例子:
font-family: 'Helvetica Neue', 'Helvetica', 'Microsoft Yahei', sans-serif;
这个 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。
浏览器配置
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字体。
使用同一颜色,感官上的颜色深浅为:黑白渲染> grayscale > sub-pixel。
iOS 和 Mac 的渲染引擎同样,但采用的是灰度渲染,默认状况下亚像素抗锯齿是关闭的,但能够通知设置开启。
因为渲染策略的不一样,字母a在不一样的浏览器和 OS 下的渲染表现也不一样。第一个是理想模型的a,第二个是灰阶渲染的a,第三个是亚像素渲染,第四个是黑白渲染。
注:从 chrome52 开始,google 中止对于老的操做系统的支持,包括 windows xp 和 windows vist a中止了 GDI 的字体渲染,从而只支持 DirectWrite。
当肯定了编码、字体类型、排版引擎、浏览器后,就要进行光栅化了,光栅化是将文字从一个向量表示(好比一个TrueType)转化到光栅或者位图表示的过程。在这个过程当中每每涉及到一些抗锯齿技术使得屏幕上的字体更加顺滑易读,这也常常会涉及到“字体微调(font hinting)”技术。
根据以上总结咱们能够看出,不一样系统预装的字体不一样,不一样浏览器的默认字体也不一样,并且还有渲染引擎的差别。因此,要想达到比较好的显示效果,须要设置好font-family
。
首先肯定要选择字体的元素应该使用的字体风格,好比是衬线字体、非衬线字体仍是 cursive
、fantasy
之类的。
优先声明英文字体,好比 Mac OS X 下有 Helvetica
也有 Arial
,但 Helvetica
(可能) 效果更好,Windows 下则通常只有 Arial
,那么写 Helvetica
, Arial
就比 Arial
, Helvetica
或者只有 Arial
更好。
绝大部分中文字体都包含英文字母和数字,可是大多数中文字体中的英文和数字部分都不是特别漂亮,因此建议对英文字体先进行声明。
而后列出中文字体,Windows下,Microsoft Yahei
是最经常使用的字体,Mac若是安装了Office,系统也会安装Microsoft Yahei
字体,可Mac下Microsoft Yahei
显示效果不是太好,因此通常把Mac的字体放在前面,Microsoft Yahei
放在后面,最后还能够跟上Linux下的WenQuanYi Micro Hei
。
最后还应该放上对应的generic family
,好比sans-serif
或者serif
。
尽可能用字体的基本名称 (好比 English locale 下显示的),而不要用本地化过的名称。除非特殊状况 (Windows 下“某些”浏览器在特定编码下只能支持本地化的字体名称)。Mac OS X 下字体名称能够用 Font Book
查到 (菜单 Preview -> Show Font Info),Windows 下字体信息在微软的网站能够获得,Linux/X11 下可使用 fc-list
命令查到。
字体名称中包含空格时记得用引号扩起来,好比"WenQuanYi Micro Hei"
。
文档开头最好指明语言,好比<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:
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码,中文测试用。
Type rendering: operating systems
Using UI System Fonts In Web Design: A Quick Practical Guide
Using the System Font in Web Content