15 字体

内容

15.1 简介

设置字体属性是样式表最常见的用法之一。不幸的是,对于字体归类,没有明确的(well-defined),被普遍接受的分类方法,而且而适用于一个字体族的术语可能不适用于其它(字体族)。例如,'italic'通常用来标记倾斜的字体,但倾斜字体也可能被标记为Oblique, Slanted, Incline, CursiveKursiv。因此,把典型的字体选择属性映射到特定字体不是个简单的问题

15.2 字体匹配策略

因为字体属性不存被普遍接受的分类,匹配字体属性时必须谨慎。这些属性以确定的顺序进行匹配,以确保匹配处理的结果尽可能跨UA一致(假定给它们提供了相同的字体库)

  1. 用户代理创建(或访问)一个含有相关CSS 2.1属性的数据库,里面存着UA支持的全部字体及其相关属性。如果有2种字体各属性完全一致,用户代理将选择其中一个
  2. 对于给定元素和该元素中的每个字符,UA都会装配适用于该元素的字体属性。使用完整的属性集,UA根据'font-family'属性来选择一种暂定的字体族。其余属性根据每个属性的匹配标准进行尝试。如果能够匹配剩余的所有属性,那么该暂定字体族就是给定元素或字符的匹配字体
  3. 如果经过第2步处理后,该'font-family'里没有匹配的字体,如果字体集里存在下一个可选的'font-family',那么就对下一个可选'font-family'重复步骤2
  4. 如果存在一种匹配字体,但它不包含当前字符的字形,如果字体集里存在下一个可选的'font-family',那么就对下一个可选的'font-family'重复步骤2
  5. 如果第2步中没有选出字体,那么就用依赖于UA的默认'font-family'并重复第2步,使用默认字体中的最佳匹配。如果一个特殊字符无法用这种字体显示,那么UA可以用其它方式来为该字符确定一个合适的的字体。UA应该把其中每个没有合适字体的字符映射到由UA选择的可见符号,最好是可供UA使用的字体中的一个“缺失字符”(missing character)字形

(上面的策略可以优化,避免对每个字符重复访问其CSS 2.1属性)

上面第2步中各个属性的匹配规则如下:

  1. 最先尝试'font-style'。如果UA的字体数据库中存在一种被标记为CSS关键字'italic'(优先)或'oblique'的字体,那么就满足'Italic'(值)。否则该值要么必须完全匹配,要么font-style匹配失败
  2. 接下来尝试'font-variant'。'small-caps'(值)会匹配(1)一个被标记为'small-caps'的字体,(2)一个合成了小型大写字母的字体,或者(3)一个所有小写字母都被替换为大写字母的字体。一个小型大写字母字体可以通过电子方式从普通字体中缩放大写字母来合成。'normal'匹配一个字体的常规(非小型大写字母)变体。字体不能没有常规变体。仅可作为小型大写字母的字体应该既可以作为'normal'字体,也可以作为'small-caps'来选择
  3. 接下来匹配'font-weight',不可能失败(见下面的'font-weight')
  4. 'font-size'必须在一个依赖于UA的公差界限(margin of tolerance)内进行匹配(典型的,可缩放字体的尺寸会被四舍五入为最相近的整数像素,而对位图字体的公差(tolerance)可能高达20%)。进一步的计算是基于'font-size'的计算值的,例如,其它属性中的'em'值

15.3 字体族'font-family'属性

'font-family'
Value:  [[ <family-name> | <generic-family> ] [, <family-name>| <generic-family>]* ] | inherit
Initial:  取决于用户代理
Applies to:  所有元素
Inherited:  yes
Percentages:  N/A
Media:  visual
Computed value:  与指定值相同

该属性值是一列按优先级排列的字体族名和/或一般字体族名。与其它大多数CSS属性不同,分量值由逗号分隔表示它们是备选项:

body { font-family: Gill, Helvetica, sans-serif }

尽管很多字体提供了“缺失字符”字形(一般是个打开的盒子),因为它的名字暗示不应该将其视为对字体中无法找到的字符的匹配(然而,应该将其视为对U+FFFD,“缺失字符”字符码位值(code point)的匹配)

有两种类型的字体族名:

<family-name>
一个字体族的名字。上一个示例中,"Gill"和"Helvetica"都是字体族
<generic-family>
上例中,最后一个值是个一般字体族名。定义了下列一般字体族名:

鼓励样式表设计者提供一个一般字体族作为最后一个备选项。一般字体族名是关键字,不要用引号包起来

字体族名要么必须用引号包起来作为字符串,要么不用引号包起来作为一系列一个或多个标识符。这意味着每个token开头的大多数标点符号和数字必须在未用引号包裹的字体系列名称中转义

例如,下列声明是非法的:

font-family: Red/Black, sans-serif;
font-family: "Lucida" Grande, sans-serif;
font-family: Ahem!, sans-serif;
font-family: test@foo, sans-serif;
font-family: #POUND, sans-serif;
font-family: Hawaii 5-0, sans-serif;

如果给定了一系列标识符作为字体族名,计算值为把该名字转换为通过用空格拼接所有标识符形成的字符串序列

为了避免转义期间的错误,建议用引号把含有除连字符外的空白字符,数字或者标点符号字符的字体族名包起来

body { font-family: "New Century Schoolbook", serif }

<BODY STYLE="font-family: '21st Century', fantasy">

刚好与关键字值相同的字体族('inherit','serif','sans-serif','monospace','fantasy','cursive')必须用引号包起来,防止与同名的关键字混淆。关键字'initial'和'default'为将来的用法保留,用作字体名时也必须用引号包起来。UA不能把这些关键字当作'<family-name>'类型匹配

15.3.1 一般字体族

一般字体族是一种fallback机制,在最坏的情况下,指定的所有字体都不可用时,(这是)能通过这种方式保留样式表编写者的一些意图。为了最佳的排版控制,应该在样式表中使用特定命名的字体

5个一般字体族的定义全都存在于所有CSS实现中(它们不一定要映射到5个不同的实际字体)。用户代理应该为一般字体族提供合理的默认选项,表达每个族的特征和可能存在的底层技术的限制

鼓励用户代理允许用户为一般字体族选择可选的替代项

15.3.1.1 serif

serif(衬线)字体的字形,作为用于CSS的术语,往往会具有修饰过的笔画,向外展开的或尖细的末端,或者是带有实际衬线的末端(包括粗衬线字体)。serif字体是典型的间隔成比例的(proportionately-spaced)。它们通常显示一个比'sans-serif'一般字体族的字体更大的介于粗和细笔画之间的变体。CSS术语'serif'适用于任何文字(script)的字体,尽管其它名字可能对于特定文字来说更熟悉一些,例如,Mincho(日文),Sung或者Song(中文),Totum或者Kodig(韩文)。这样描述的任何字体都可以代表一般'serif'字体族

适合该描述的字体示例包括:

拉丁(Latin)字体 Times New Roman, Bodoni, Garamond, Minion Web, ITC Stone Serif, MS Georgia, Bitstream Cyberbit
希腊(Greek)字体 Bitstream Cyberbit
斯拉夫字母(Cyrillic)字体 Adobe Minion Cyrillic, Excelsior Cyrillic Upright, Monotype Albion 70, Bitstream Cyberbit, ER Bukinist
希伯来(Hebrew)字体 New Peninim, Raanana, Bitstream Cyberbit
日文(Japanese)字体 Ryumin Light-KL, Kyokasho ICA, Futo Min A101
阿拉伯(Arabic)字体 Bitstream Cyberbit
彻罗基(Cherokee)字体 Lo Cicero Cherokee

15.3.1.2 sans-serif

sans-serif(无衬线)字体的字形,作为用于CSS的术语,往往会具有笔画清晰的末端--带有一点或者没有向外展开的,交错笔画,或者其它装饰。sans-serif字体是典型的间隔成比例的(proportionately-spaced)。与'serif'族的字体相比,它们通常在笔画粗细间有一点变化。CSS术语'sans-serif'适用于任何文字(script),尽管其它名字可能对于特定文字来说更熟悉,例如,Gothic(日文),Kai(中文)或者Pathang(韩文)。这样描述的任何字体都可以代表一般'sans-serif'字体族

适合该描述的字体示例包括:

拉丁(Latin)字体 MS Trebuchet, ITC Avant Garde Gothic, MS Arial, MS Verdana, Univers, Futura, ITC Stone Sans, Gill Sans, Akzidenz Grotesk, Helvetica
希腊(Greek)字体 Attika, Typiko New Era, MS Tahoma, Monotype Gill Sans 571, Helvetica Greek
斯拉夫字母(Cyrillic)字体 Helvetica Cyrillic, ER Univers, Lucida Sans Unicode, Bastion
希伯来(Hebrew)字体 Arial Hebrew, MS Tahoma
日文(Japanese)字体 Shin Go, Heisei Kaku Gothic W5
阿拉伯(Arabic)字体 MS Tahoma

15.3.1.3 cursive

cursive(手写体)字体的字形,作为用于CSS的术语,一般具有连笔(joining strokes)或者其它除斜体字体外的手写特征。字形部分或整个连在一起,结果看起来更像手写笔或者毛笔书写的,而不是打印的字母(printed letterwork)。对于某些文字而言,例如阿拉伯(Arabic),字体差不多总是cursive。CSS术语'cursive'适用于任何文字(script),尽管其它名字,例如Chancery,Brush,Swing和Script也用于字体名

适合该描述的字体示例包括:

拉丁(Latin)字体 Caflisch Script, Adobe Poetica, Sanvito, Ex Ponto, Snell Roundhand, Zapf-Chancery
斯拉夫字母(Cyrillic)字体 ER Architekt
希伯来(Hebrew)字体 Corsiva
阿拉伯(Arabic)字体 DecoType Naskh, Monotype Urdu 507

15.3.1.4 fantasy

Fantasy字体,用于CSS,主要是装饰性的,但仍然具有字符表现(与不表现字符的Pi或者Picture字体相反)。示例包括:

拉丁(Latin)字体 Alpha Geometrique, Critter, Cottonwood, FB Reactor, Studz

15.3.1.5 monospace

monospace的唯一标准是所有字形都具有相等的固定宽度(这会让一些文字,例如,阿拉伯文(Arabic),看起来很古怪)。效果与手动打字机类似,通常用来设置计算机代码的样例

适合该描述的字体示例包括:

拉丁(Latin)字体 Courier, MS Courier New, Prestige, Everson Mono
希腊(Greek)字体 MS Courier New, Everson Mono
斯拉夫字母(Cyrillic)字体 ER Kurier, Everson Mono
日文(Japanese)字体 Osaka Monospaced
彻罗基(Cherokee)字体 Everson Mono

15.4 字体样式'font-style'属性

'font-style'
Value:  normal | italic | oblique | inherit
Initial:  normal
Applies to:  所有元素
Inherited:  yes
Percentages:  N/A
Media:  visual
Computed value:  与指定值相同

'font-style'属性可以选择一个字体族中的常规(normal(有时称为"roman"或者"upright")),斜体(italic)和倾斜(oblique)字体

'normal'值会在UA的字体数据库中选择一个被分类为'normal'的字体,而'oblique'会选择一个被标记为'oblique'的字体。'italic'值会选择一个被标记为'italic'的字体,或者如果(italic)不可用,就选择被标记为'oblique'的字体

UA的字体数据库中被标记为'oblique'的字体可能实际上已经通过电子方式倾斜常规字体生成了

典型的,名字中含有Oblique,Slanted或者Incline的字体在UA的字体数据库中会被标记为'oblique'。名字中含有Italic,Cursive或者Kursiv的字体会被标记为'italic'

h1, h2, h3 { font-style: italic }
h1 em { font-style: normal }

上例中,'H1'中被强调的文本将以常规字体呈现

15.5 小型大写字母'font-variant'属性

'font-variant'
Value:  normal | small-caps | inherit
Initial:  normal
Applies to:  所有元素
Inherited:  yes
Percentages:  N/A
Media:  visual
Computed value:  与指定值相同

字体族中的另一种变体类型是小型大写字母(small-caps)。在小型大写字母字体中,小写字母看起来和大写字母很相似,但尺寸更小,而且比例稍有差异。可以用'font-variant'属性选择这种字体

'normal'值会选择一个非小型大写字母字体,'small-caps'会选择一个小型大写字母字体。如果小型大写字母字体是通过把常规字体中的小写字母替换为缩放的大写字符创建的,在CSS 2.1中也可以接受(但不是必须的)。万不得已时,大写字母将被用作小型大写字母字体的替代品

下例会让'H3'元素为小型大写字母,所有被强调的单词都是倾斜,'H3'中所有被强调的单词为倾斜小型大写字母:

h3 { font-variant: small-caps }
em { font-style: oblique }

字体族中还可能存在其它变体,例如,老式数字(old-style numerals),小型大写数字(small-caps numerals),缩紧或者扩宽的字体等等。CSS 2.1没有可以选择这些字体的属性

注意:就该属性会让文本被转换为大写形式而言,也可以考虑应用'text-transform'

15.6 字重'font-weight'属性

'font-weight'
Value:  normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
Initial:  normal
Applies to:  所有元素
Inherited:  yes
Percentages:  N/A
Media:  visual
Computed value:  见下文

'font-weight'属性用来选择字体粗细程度。值为'100'到'900'的有序序列,每个数字表示一个粗细程度,至少和它的前一个一样粗(dark)。关键字'normal'等同于'400','bold'等同于'700'。除'normal'和'bold'外的关键字经常与字体名混淆,因此一般在列出的9个数字分级中选择

p { font-weight: normal }   /* 400 */
h1 { font-weight: 700 }     /* bold */

'bolder'和'lighter'值用来相对于从父级继承到的粗细程度选择字体的粗细程度:

strong { font-weight: bolder }

典型的,字体(字体数据)通常具有一个或多个属性,其值是描述字体“粗细”的名称。这些粗细程度名没有公认的,通用含义。它们的主要作用是区分单一字体族中不同的粗细程度(darkness)。用法在各个字体族之间差异很大,例如,一个bold字体可能被描述为Regular,Roman,Book,Medium,Semi-或者DemiBold,Bold或者Black,取决于设计中"normal"字体有多粗(black)。因为没有标准的名字用法,weight属性值在CSS 2.1中是以数字分级给出的,值'400'(或者'normal')对应该字体族的"normal"文本字体。典型的,与该字体相关的weight名为Book,Regular,Roman,Normal或者Medium

字体族中其它weight与数字weight值的关联只是想要保留字体族中粗细程度的顺序。然而,如下启发式方法描述了这种情况下如何完成分配:

一旦字体族的weight被映射到CSS分级上,缺少的weight就按照如下规则选择:

下面的两个例子展示了典型的映射

假设"Rattlesnake"字体族中的4种weight,从最细到最粗为:Regular,Medium,Bold,Heavy

font-weight映射的第一个例子
Available faces Assignments Filling the holes
"Rattlesnake Regular" 400 100, 200, 300
"Rattlesnake Medium" 500  
"Rattlesnake Bold" 700 600
"Rattlesnake Heavy" 800 900

假设"Ice Prawn"字体族中的6种weight:Book,Medium,Bold,Heavy,Black,ExtraBlack。注意,这种情况下,用户代理已经决定了给"Ice Prawn ExtraBlack"分配数字分级

font-weight映射的第二个例子
Available faces Assignments Filling the holes
"Ice Prawn Book" 400 100, 200, 300
"Ice Prawn Medium" 500  
"Ice Prawn Bold" 700 600
"Ice Prawn Heavy" 800  
"Ice Prawn Black" 900  
"Ice Prawn ExtraBlack" (none)  

值为'bolder'和'lighter'表示相对于父元素的weight。基于继承到的weight值,weight的应用值按照下表来计算。子元素继承weight的计算值,而不是'bolder'或者'lighter'

'bolder'和'lighter'的含义
Inherited value bolder lighter
100 400 100
200 400 100
300 400 100
400 700 100
500 700 100
600 900 400
700 900 400
800 900 700
900 900 700

上表相当于给出一个含有normal和bold字体以及thin和heavy字体的字体族,从中选择下一个相对更粗或者更细的字体。想要更好地控制给定元素的精确weight值的编写者应该使用数字分级而不是相对粗细程度

无法保证每个'font-weight'值都存在一个更粗的字体。例如,有些字体可能只有normal和bold字体,而其它的可能具有8种字重。无法保证UA会怎样把字体族中的字体映射到weight值。唯一能保证的是给定值的字体不会比lighter值对应的字体更细

15.7 字体大小'font-size'属性

'font-size'
Value:  <absolute-size> | <relative-size> | <length> | <percentage> | inherit
Initial:  medium
Applies to:  所有元素
Inherited:  yes
Percentages:  参照继承的字体大小
Media:  visual
Computed value:  绝对的值

字体大小对应的em square(字元的正方形空间),是一个用于排版的概念。注意某些字形可能会从其em square中伸出来(bleed outside)。值含义如下:

<absolute-size>
一个<absolute-size>关键字是字体大小表的索引,该表由UA计算和维护。可能的值为:

[ xx-small | x-small | small | medium | large | x-large | xx-large ]

下表为absolute-size到HTML标题和绝对的font-size的映射提供了用户代理指南。'medium'值是用户代理的偏好字体大小,并被用作参考中间值

CSS absolute-size values xx-small x-small small medium large x-large xx-large  
HTML font sizes 1   2 3 4 5 6 7

实现者应该为'medium'字体大小相关的absolute-size关键字和特殊设备及其特征(例如,设备分辨率)建立一个比例因子表

不同媒体可能需要不同的比例因子。计算该表时,UA还应该考虑字体的质量和可用性。不同字体族对应的表可能不一样

注意 1 为了保持可读性,应用这些指南的UA应该避免在计算机显示器上创建小于9像素每EM单元(9 pixels per EM unit)的font-size

注意 2 CSS1中,建议的相邻索引间的比例因子为1.5,此时用户体验最佳。CSS2中,建议的计算机屏幕上相邻索引间的比例因子为1.2,对于小尺寸仍然会出问题。实现经验表明相邻absolute-size关键字间固定的比例是有问题的,本规范推荐这种固定比例

<relative-size>
<relative-size>关键字根据字体大小表和父元素的字体大小来解释。可能的值为:[ larger | smaller ]。例如,如果父元素的字体大小为'medium',值为'larger'会让当前元素的字体大小变成'large'。如果父元素的大小不贴近表格项,UA可以自由地在表格项中插值或者舍入为最近的表格项。如果数字值超出了关键字的话,UA可能不得不推算表格值

计算元素的字体大小时,长度和百分比值不应该考虑字体大小表

负值是非法的

在所有其它属性上,'em'和'ex'长度值参照当前元素字体大小的计算值。在'font-size'属性上,这些长度单位参照其父元素的字体大小的计算值

注意,一个应用程序可能会重新解释一个显式的大小,这取决于上下文。例如,在VR场景中,因为透视失真(perspective distortion),字体可能有不同的大小

示例:

p { font-size: 16px; }
@media print {
	p { font-size: 12pt; }
}
blockquote { font-size: larger }
em { font-size: 150% }
em { font-size: 1.5em }

15.8 简写的字体属性'font'属性

'font'
Value:  [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
Initial:  见单独的各个属性
Applies to:  所有元素
Inherited:  yes
Percentages:  见单独的各个属性
Media:  visual
Computed value:  见单独的各个属性

'font'属性的描述见下文,一个用来在样式表中一次性设置'font-style''font-variant''font-weight''font-size''line-height''font-family'的简写属性。该属性的语法基于传统排版简写的表示法,用来设置字体相关的多个属性

所有字体相关的属性都会先被重置为其初始值,包括上文中列出的那些。然后,'font'简写中,那些给定了明确值的属性被设置为给定的值。关于合法值和初始值的定义,见之前定义的各属性

p { font: 12px/14px sans-serif }
p { font: 80% sans-serif }
p { font: x-large/110% "New Century Schoolbook", serif }
p { font: bold italic large Palatino, serif }
p { font: normal small-caps 120%/120% fantasy }

第二条规则中,字体大小百分比值('80%')参照其父元素的字体大小。第三条规则中,行高百分比参照该元素自身的字体大小

上面前三条规则中,'font-style','font-variant'和'font-weight'都没有显式提及,这意味着它们三个全都会被设置为其初始值('normal')。第四条规则把'font-weight'设置为'bold',把'font-style'设置为'italic',并且把'font-variant'隐式设置为'normal'

第五条规则设置了'font-variant'('small-caps'),'font-size'(其父级字体的120%),'line-height'(120%乘以字体大小)和'font-family'('fantasy')。因此,关键字'normal'应用于两个剩余属性:'font-style'和'font-weight'

下列值引用系统字体

caption
用于标题控件的字体(例如,按钮,下拉框等等)
icon
用于标记图标的字体
menu
用于菜单的字体(例如,下拉菜单和菜单列表)
message-box
用于对话框的字体
small-caption
用于标记小控件的字体
status-bar
用于窗口状态栏的字体

系统字体只能作为整体来设置,也就是说,会同时设置字体族,大小,粗细程度,样式等等。如果需要的话,随后可以单独改变这些值。如果给定平台上不存在具有指定的特征的字体,用户代理应该智能的替换(例如,'caption'字体更小的版本可以用作'small-caption'字体),或者替换为用户代理默认字体。至于常规(regular)字体,对于一个系统字体,如果所有单独属性都不是操作系统的可用用户偏好的一部分,这些属性应该被设置为其初始值

这就是为什么该属性“几乎”是一个简写属性:系统字体只能用该属性来指定,而不是用'font-family'自身,所以'font'让编写者能做的要比子属性加起来还要多。然而,单独的属性,例如'font-weight'给定取自系统字体的值后,仍然可以单独改变

示例:

button { font: 300 italic 1.3em/1.7em "FB Armada", sans-serif }
button p { font: menu }
button p em { font-weight: bolder }

如果一个特殊系统中用于下拉菜单字体恰好是,例如,9-point Charcoal,weight为600,那么作为BUTTON后代的P元素将被显示成这条规则的效果:

button p { font: 600 9px Charcoal }

因为'font'简写属性会把所有没有显式给定值的属性重置为其初始值,与这个声明的效果一样:

button p {
  font-family: Charcoal;
  font-style: normal;
  font-variant: normal;
  font-weight: 600;
  font-size: 9px;
  line-height: normal;
}