欢迎光临散文网 会员登陆 & 注册

知识分享!CSS字体,从Level 1到Level 3

2020-12-29 10:03 作者:光耀三十洲  | 我要投稿

本文是阅读 CSS 标准文档的笔记,也是对 CSS 字体相关知识的一个梳理。

Cascading Style Sheets, level 1

CSS 1 定义的字体属性包括:font-familyfont-stylefont-variantfont-weightfont-sizefont。其算法要求 UA(User Agent,用户代理) 对给定元素中的字符逐个查找匹配的 CSS 属性,首先尝试匹配font-style,比如italicoblique。然后匹配font-variantnormal匹配非small-caps(小型大写) 字体,而small-caps则匹配 (1) 标识为small-caps的字体 (2) 合成小型大写字母的字体 (3) 将小写字母替换为大写字母的字体(小型大写字母可以通过将normal字体的大写字母缩小来实现)。接着匹配font-weightfont-size,这两个属性都是必须匹配成功的。

font-family是一个按照优先级排列的字体或通用字体名字的列表,每个名字以逗号分隔,表示多选一。

body { font-family: gill, helvetica, sans-serif; }复制代码

有两种值:字体名和通用字体名。在上面的例子中,gillhelvetica就是明确指定的字体名,而sans-serif则是通用字体名。CSS 1 定义了 5 种通用字体:

  • serif:衬线

  • sans-serif:非衬线

  • cursive:手写

  • fantasy:装饰

  • monospace:等宽

通常,除了指定特定的字体名,最后都应该指定一个通用字体名。另外,如果字体名包含空格,必须用引号括起来。

font-style有 3 个值:normalitalicobliquenoraml就是正常字体,而italic是斜体,oblique有可能是将正常字体倾斜后得到的。对于italic而言,如果没有italic字体,则使用oblique

通常字体名字中包含 Oblique、Slanted 或 Incline 的,UA 通常将其归类为oblique;而字体名字中包含 Italic、Cursive 或 Kursiv 的,UA 则将其归类为italic

font-variant主要用于指定normalsmall-caps。真正的small-caps字体的字母比大写字母小一些,而且比例也稍有差异。但是,如果不是真正的small-caps字体,也可以将normal字体中的大写字母缩小后代替。实在不行,也可以直接用大写字母。

CSS 1 只支持small-caps一种变体,不支持老式数字、小型大写数字、紧缩或疏松字母等其他变体。

font-weight选择字重,有关键字值normalboldbolderlighter和数值 100~900,表示笔画越来越粗。normal对应 400,bold对应 700。bolderlighter则相对于从父元素继承的字重加粗或变细。现实中的字体 (字体数据) 都会有一个或几个属性的值用于描述字体的 "重量"。但不同字体使用的属性值并不统一,比如包含以下关键字的值似乎都可以认为是粗体:Regular、Roman、Book、Medium、Semi-、DemiBold、Bold 或 Black,具体要看其normal字形有多重。正因为如此,CSS 1 才定义了一系列数值。OpenType 使用 9 个数值区分字重,可以直接对应。但并非所有字体都有那么多字重,CSS 1 为此也定义了如何向前或向后 "寻值",比如 500 如果没有,则用 400。

font-size定义了绝对值、相对值、长度值和百分比值。绝对值包括xx-smallx-smallsmallmediumlargex-largexx-large等关键字,它们在 UA 里以 1.5 倍的比例差异保存着绝对大小。相对值有largersmaller关键字,取决于父元素文本大小的绝对值。不允许负值。

最后,font是以上所有属性的简写属性,可以同时设置font-stylefont-variantfont-weightfont-sizeline-heightfont-family。这个属性借鉴了传统排版中的同时设置多个属性的简写法。

Cascading Style Sheets Level 2 Revision 1 (CSS 2.1)

CSS 1 奠定了字体属性的格局。CSS 2.1 仅对 CSS 1 进行了补充和扩展。

首先,CSS 1 只规定font-family最后要使用一种通用字体作为后备,并没有详细说明这些字体的特点和举例。CSS 2.1 则详细解读了serifsans-serifcursivefantasymonospace

其次,对所有属性统一增加了inherit关键字。而且,font-variant仍然只支持small-caps一种变体形式。

最后,CSS 2.1 比较重要的一个增补,是为font简写属性增加了 6 种系统字体关键字:captioniconmenumessage-boxsmall-captionstatus-bar。比如,通过font: menu;可以让网页中的某个元素继承系统菜单中使用的字体及属性。假设系统菜单使用了 12 像素、字重 600 的 Times,则font: menu就相当于:

font: 600 12px Times;复制代码

因为系统字体的样式只能整体继承,不能单独获取,所以只能通过font简写属性来继承系统字体的样式。另外,由于font简写属性会将所有没有明确给出的值重置为相应的初始值,所以上面的声明又相当于:

font-family: Times; font-style: normal; font-variant: normal; font-weight: 600; font-size: 12px; line-height: normal;复制代码

CSS Fonts Module Level 3

我们知道,从 CSS3 开始,CSS 规范被拆成众多模块单独升级,新的需求也会作为一个新模块来立项并标准化。在 CSS 2.1 之后,CSS 中关于字体的内容就独立为 CSS3 Fonts 模块。同时为了支持可下载的自定义字体,又创建了 CSS3 Web Fonts 模块。

但最终,CSS3 Fonts 和 CSS3 Web Fonts 合并为 CSS Fonts Module Level 3(以下简称 "ML3")。后来,ML3 中涉及字体加载的内容,又独立为 CSS Font Loading Module Level 3。

ML3 进一步细化了 CSS 字体属性的内涵和外延。比如,对于font-family字体列表中出现的字体名。ML3 就进一步说明:

字体名只指定一种字体的名字,而不能指定该种字体中某一个字体。比如,Futura 是一种字体,它又包含 Futura Medium、Futura Medium Italic、Futura Condensed Medium 和 Futura Condensed ExtraBold 字体。

ML3 还增加了font-stretch属性,用于从字体中选择正常、紧缩或疏松的字形,有以下关键字值:

  • ultra-condensed

  • extra-condensed

  • condensed

  • semi-condensed

  • normal

  • semi-expanded

  • expanded

  • extra-expanded

  • ultra-expanded

另外,对于之前font-style属性所谓的 "伪斜体" 关键字oblique,也可以通过font-synthesis属性设置是否启用。因为对某些文字,比如西里尔文字,真正的斜体与人工合成的斜体差别很大。比如,下面的规则禁止 UA 合成阿拉伯文斜体:

*:lang(ar) { font-synthesis: none; }复制代码

ML3 还增加了font-size-adjust属性,用于在使用备用字体时,依然能保持原本所要使用字体的纵横比(小写字母与大写字母的相对高度),从而保证可读性。

@font-face

如前所述,ML3 最大的变化就是增加了 Font Resource 一节。这一节定义了@font-face规则,@font-face规则用于定义一个(种)新的字体,其属性由包含在花括号内的规则描述符声明决定。其中,font-familysrc是必需的描述符。(注意,在普通 CSS 声明里,font-familysrc是属性,而在@font-face规则里,因为是用于定义新字体,所以font-familysrc就成了描述符,即用于描述新字体的属性。)

font-family描述符定义字体名字,会覆盖底层字体文件中的名字,而且如果名字跟系统字体冲突,还会覆盖系统字体。

src描述符定义字体的来源,其值为按优先次序排列的来源列表,来源本地使用local()引入,来源外部使用url()引入。使用url()引入外部字体时,可以用format()添加字体格式的提示。ML3 定义的有效字体格式字符串有:

此外,由于 OpenType 是 TrueType 超集和扩展,字符串 "truetype" 和 "opentype" 表示的意思是一样的。

在使用local()加载本地字体时,因为 UA 要匹配字体文件中包含的全名,而同一字体在不同平台下的全名可能不一样,因此需要指定所有可能的名字,以便跨平台使用。

local()函数很有用,比如上面的例子其实是为不同平台下的同一款字体创建了一个统一的别名。再比如下面的例子,用于将一种大字体中永远都不会被引用到的字体抽取出来:

另外,ML3 规定 UA 只能优先使用字体文件中的英文全名来匹配字体。即便用户操作系统将地区设置为比如德国、芬兰,而字体文件中也有德语、芬兰语的字体全名,也要匹配英文全名,这是为了全平台统一起见。因此下面h2最终会使用默认的衬线字体:

font-stylefont-weightfont-stretch这三个描述符的值跟对应属性的值一样,只是不允许使用相对关键字bolderlighter

综上所述,@font-face规则的引入为 CSS 字体的使用提供了很大便利。事实上,只有结合马上要出场的unicode-range描述符,@font-face规则才能发挥出最大的潜力。

unicode-range

unicode-range描述符用于指定当前定义字体支持的 Unicode 码点 (code point),是一个逗号分隔的 Unicode 范围值。这相当于定义了一个字符集,UA 可以根据这个字符集来决定针对某个文字是否需要下载新字体。

Unicode 范围值支持单个码点 (如U+416)、码点区间 (如U+400-4ff) 和通配范围 (如U+4??)。

那么 Unicdoe 范围或者说字符范围 (字符集) 有什么用呢?可以用多个@font-face规则和不同的 Unicode 范围共同定义一个复合型字体。换句话说,可以在一个自定义字体中包含来自不同语言文字的多个字体的不同字形,也可以定义一个只包含某种字体常用或罕用字符的新字体。如果同一个新字体的多个@font-face规则中的 Unicode 范围有重合,那么最后定义的规则先匹配。

下面的规则会基于日文字体 MSMincho 和英文字体 Gentium 定义一个新字体 JapaneseWithGentium,其中拉丁字母的字形来自 Gentium 字体,其他字形来自 MSMincho。

利用@font-face的层叠规则,还可以实现对字体的 "按需下载"。比如,在下面的例子,如果只需要拉丁字符的字形,UA 只会下载 DroidSans.woff。

ML3 规定,@font-face指定的字体资源采用懒加载策略,即如果不用到,就不下载。样式表里可以定义很多@font-face,但 UA 必须只下载那些样式规则中引用到的字体。有一个例外就是当自定义字体作为后备字体时,UA 可以提前下载,比如:

一般情况下,页面都会先于字体加载完。此时使用自定义字体的文本应该如何显示呢?ML3 规定 UA 可以按照自定义字体不可用的情形来渲染字体,或者用后备字体将文本渲染为透明的。但在自定义字体下载失败后,UA 必须显示文本。因此,ML3 也要求样式表作者指定与自定义字体大小类似的后备字体。

关于字体的获取,ML3 规定必须使用启用 CORS 的手段,使用Anonymous模式,将referrer设置为样式表的 URL,将origin设置为包含样式表的文档的 URL。

关于字体匹配,ML3 是有史以来最详细的。它增加了font-stretch的匹配,罗列出了font-style所有可能的匹配情形。small-caps完全从字体匹配流程中剥离,由字体特性来处理。要求必须使用 Unicode 变体选择符。簇序列作为一个单位匹配。

字体特性

如前所述,font-variant属性一直以来只有一个small-caps变体。而实践中使用的字体远不止只有小型大写字母一种变化形式。为此,ML3 扩展了font-variant属性,使其成为了控制所有样式相关字体特性的一个简写属性。

换句话说,font-variant有了font-variant-ligaturesfont-variant-postionfont-variant-capsfont-variant-numericfont-variant-east-asian等具体属性。

字体特性可以通过font-variantfont-feature-settings来启用。具体细节因为涉及英文字体的很多古老传统,有兴趣的读者可以自行学习。

尾声

CSS Font Module Level 3 在 2018 年 9 月成为 W3C 推荐标准,随即又开始了 CSS Fonts Module Level 4,包含了一些 CSS 字体相关的试验性特性。另外,从 CSS Font Module Level 3 中独立出去的 CSS Font Loading Module Level 3 已经得到主流浏览器较新版本的支持。


了解更多,请点击:https://www.bilibili.com/video/BV13b411g78D


作者:为之漫笔
链接:https://juejin.cn/post/6911149782446669838
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


知识分享!CSS字体,从Level 1到Level 3的评论 (共 条)

分享到微博请遵守国家法律