知識分享!CSS字體,從Level 1到Level 3
本文是閱讀 CSS 標(biāo)準(zhǔn)文檔的筆記,也是對 CSS 字體相關(guān)知識的一個(gè)梳理。
Cascading Style Sheets, level 1
CSS 1 定義的字體屬性包括:font-family
、font-style
、font-variant
、font-weight
、font-size
和font
。其算法要求 UA(User Agent,用戶代理) 對給定元素中的字符逐個(gè)查找匹配的 CSS 屬性,首先嘗試匹配font-style
,比如italic
和oblique
。然后匹配font-variant
,normal
匹配非small-caps
(小型大寫) 字體,而small-caps
則匹配 (1) 標(biāo)識為small-caps
的字體 (2) 合成小型大寫字母的字體 (3) 將小寫字母替換為大寫字母的字體(小型大寫字母可以通過將normal
字體的大寫字母縮小來實(shí)現(xiàn))。接著匹配font-weight
和font-size
,這兩個(gè)屬性都是必須匹配成功的。
font-family
是一個(gè)按照優(yōu)先級排列的字體或通用字體名字的列表,每個(gè)名字以逗號分隔,表示多選一。
body { font-family: gill, helvetica, sans-serif; }復(fù)制代碼
有兩種值:字體名和通用字體名。在上面的例子中,gill
和helvetica
就是明確指定的字體名,而sans-serif
則是通用字體名。CSS 1 定義了 5 種通用字體:
serif
:襯線sans-serif
:非襯線cursive
:手寫fantasy
:裝飾monospace
:等寬
通常,除了指定特定的字體名,最后都應(yīng)該指定一個(gè)通用字體名。另外,如果字體名包含空格,必須用引號括起來。
font-style
有 3 個(gè)值:normal
、italic
和oblique
。noraml
就是正常字體,而italic
是斜體,oblique
有可能是將正常字體傾斜后得到的。對于italic
而言,如果沒有italic
字體,則使用oblique
。
通常字體名字中包含 Oblique、Slanted 或 Incline 的,UA 通常將其歸類為oblique
;而字體名字中包含 Italic、Cursive 或 Kursiv 的,UA 則將其歸類為italic
。
font-variant
主要用于指定normal
和small-caps
。真正的small-caps
字體的字母比大寫字母小一些,而且比例也稍有差異。但是,如果不是真正的small-caps
字體,也可以將normal
字體中的大寫字母縮小后代替。實(shí)在不行,也可以直接用大寫字母。
CSS 1 只支持small-caps
一種變體,不支持老式數(shù)字、小型大寫數(shù)字、緊縮或疏松字母等其他變體。
font-weight
選擇字重,有關(guān)鍵字值normal
、bold
、bolder
、lighter
和數(shù)值 100~900,表示筆畫越來越粗。normal
對應(yīng) 400,bold
對應(yīng) 700。bolder
和lighter
則相對于從父元素繼承的字重加粗或變細(xì)。現(xiàn)實(shí)中的字體 (字體數(shù)據(jù)) 都會有一個(gè)或幾個(gè)屬性的值用于描述字體的 "重量"。但不同字體使用的屬性值并不統(tǒng)一,比如包含以下關(guān)鍵字的值似乎都可以認(rèn)為是粗體:Regular、Roman、Book、Medium、Semi-、DemiBold、Bold 或 Black,具體要看其normal
字形有多重。正因?yàn)槿绱?,CSS 1 才定義了一系列數(shù)值。OpenType 使用 9 個(gè)數(shù)值區(qū)分字重,可以直接對應(yīng)。但并非所有字體都有那么多字重,CSS 1 為此也定義了如何向前或向后 "尋值",比如 500 如果沒有,則用 400。
font-size
定義了絕對值、相對值、長度值和百分比值。絕對值包括xx-small
、x-small
、small
、medium
、large
、x-large
和xx-large
等關(guān)鍵字,它們在 UA 里以 1.5 倍的比例差異保存著絕對大小。相對值有larger
和smaller
關(guān)鍵字,取決于父元素文本大小的絕對值。不允許負(fù)值。
最后,font
是以上所有屬性的簡寫屬性,可以同時(shí)設(shè)置font-style
、font-variant
、font-weight
、font-size
、line-height
和font-family
。這個(gè)屬性借鑒了傳統(tǒng)排版中的同時(shí)設(shè)置多個(gè)屬性的簡寫法。
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1)
CSS 1 奠定了字體屬性的格局。CSS 2.1 僅對 CSS 1 進(jìn)行了補(bǔ)充和擴(kuò)展。
首先,CSS 1 只規(guī)定font-family
最后要使用一種通用字體作為后備,并沒有詳細(xì)說明這些字體的特點(diǎn)和舉例。CSS 2.1 則詳細(xì)解讀了serif
、sans-serif
、cursive
、fantasy
和monospace
。
其次,對所有屬性統(tǒng)一增加了inherit
關(guān)鍵字。而且,font-variant
仍然只支持small-caps
一種變體形式。
最后,CSS 2.1 比較重要的一個(gè)增補(bǔ),是為font
簡寫屬性增加了 6 種系統(tǒng)字體關(guān)鍵字:caption
、icon
、menu
、message-box
、small-caption
和status-bar
。比如,通過font: menu;
可以讓網(wǎng)頁中的某個(gè)元素繼承系統(tǒng)菜單中使用的字體及屬性。假設(shè)系統(tǒng)菜單使用了 12 像素、字重 600 的 Times,則font: menu
就相當(dāng)于:
font: 600 12px Times;復(fù)制代碼
因?yàn)橄到y(tǒng)字體的樣式只能整體繼承,不能單獨(dú)獲取,所以只能通過font
簡寫屬性來繼承系統(tǒng)字體的樣式。另外,由于font
簡寫屬性會將所有沒有明確給出的值重置為相應(yīng)的初始值,所以上面的聲明又相當(dāng)于:
font-family: Times;
font-style: normal;
font-variant: normal;
font-weight: 600;
font-size: 12px;
line-height: normal;復(fù)制代碼
CSS Fonts Module Level 3
我們知道,從 CSS3 開始,CSS 規(guī)范被拆成眾多模塊單獨(dú)升級,新的需求也會作為一個(gè)新模塊來立項(xiàng)并標(biāo)準(zhǔn)化。在 CSS 2.1 之后,CSS 中關(guān)于字體的內(nèi)容就獨(dú)立為 CSS3 Fonts 模塊。同時(shí)為了支持可下載的自定義字體,又創(chuàng)建了 CSS3 Web Fonts 模塊。
但最終,CSS3 Fonts 和 CSS3 Web Fonts 合并為 CSS Fonts Module Level 3(以下簡稱 "ML3")。后來,ML3 中涉及字體加載的內(nèi)容,又獨(dú)立為 CSS Font Loading Module Level 3。
ML3 進(jìn)一步細(xì)化了 CSS 字體屬性的內(nèi)涵和外延。比如,對于font-family
字體列表中出現(xiàn)的字體名。ML3 就進(jìn)一步說明:
字體名只指定一種字體的名字,而不能指定該種字體中某一個(gè)字體。比如,F(xiàn)utura 是一種字體,它又包含 Futura Medium、Futura Medium Italic、Futura Condensed Medium 和 Futura Condensed ExtraBold 字體。
ML3 還增加了font-stretch
屬性,用于從字體中選擇正常、緊縮或疏松的字形,有以下關(guān)鍵字值:
ultra-condensed
extra-condensed
condensed
semi-condensed
normal
semi-expanded
expanded
extra-expanded
ultra-expanded
另外,對于之前font-style
屬性所謂的 "偽斜體" 關(guān)鍵字oblique
,也可以通過font-synthesis
屬性設(shè)置是否啟用。因?yàn)閷δ承┪淖郑热缥骼餇栁淖?,真正的斜體與人工合成的斜體差別很大。比如,下面的規(guī)則禁止 UA 合成阿拉伯文斜體:
*:lang(ar) { font-synthesis: none; }復(fù)制代碼
ML3 還增加了font-size-adjust
屬性,用于在使用備用字體時(shí),依然能保持原本所要使用字體的縱橫比(小寫字母與大寫字母的相對高度),從而保證可讀性。
@font-face
如前所述,ML3 最大的變化就是增加了 Font Resource 一節(jié)。這一節(jié)定義了@font-face
規(guī)則,@font-face
規(guī)則用于定義一個(gè)(種)新的字體,其屬性由包含在花括號內(nèi)的規(guī)則描述符聲明決定。其中,font-family
和src
是必需的描述符。(注意,在普通 CSS 聲明里,font-family
和src
是屬性,而在@font-face
規(guī)則里,因?yàn)槭怯糜诙x新字體,所以font-family
和src
就成了描述符,即用于描述新字體的屬性。)
font-family
描述符定義字體名字,會覆蓋底層字體文件中的名字,而且如果名字跟系統(tǒng)字體沖突,還會覆蓋系統(tǒng)字體。
src
描述符定義字體的來源,其值為按優(yōu)先次序排列的來源列表,來源本地使用local()
引入,來源外部使用url()
引入。使用url()
引入外部字體時(shí),可以用format()
添加字體格式的提示。ML3 定義的有效字體格式字符串有:

此外,由于 OpenType 是 TrueType 超集和擴(kuò)展,字符串 "truetype" 和 "opentype" 表示的意思是一樣的。

在使用local()
加載本地字體時(shí),因?yàn)?UA 要匹配字體文件中包含的全名,而同一字體在不同平臺下的全名可能不一樣,因此需要指定所有可能的名字,以便跨平臺使用。

local()
函數(shù)很有用,比如上面的例子其實(shí)是為不同平臺下的同一款字體創(chuàng)建了一個(gè)統(tǒng)一的別名。再比如下面的例子,用于將一種大字體中永遠(yuǎn)都不會被引用到的字體抽取出來:

另外,ML3 規(guī)定 UA 只能優(yōu)先使用字體文件中的英文全名來匹配字體。即便用戶操作系統(tǒng)將地區(qū)設(shè)置為比如德國、芬蘭,而字體文件中也有德語、芬蘭語的字體全名,也要匹配英文全名,這是為了全平臺統(tǒng)一起見。因此下面h2
最終會使用默認(rèn)的襯線字體:

font-style
、font-weight
和font-stretch
這三個(gè)描述符的值跟對應(yīng)屬性的值一樣,只是不允許使用相對關(guān)鍵字bolder
和lighter
。
綜上所述,@font-face
規(guī)則的引入為 CSS 字體的使用提供了很大便利。事實(shí)上,只有結(jié)合馬上要出場的unicode-range
描述符,@font-face
規(guī)則才能發(fā)揮出最大的潛力。
unicode-range
unicode-range
描述符用于指定當(dāng)前定義字體支持的 Unicode 碼點(diǎn) (code point),是一個(gè)逗號分隔的 Unicode 范圍值。這相當(dāng)于定義了一個(gè)字符集,UA 可以根據(jù)這個(gè)字符集來決定針對某個(gè)文字是否需要下載新字體。
Unicode 范圍值支持單個(gè)碼點(diǎn) (如U+416
)、碼點(diǎn)區(qū)間 (如U+400-4ff
) 和通配范圍 (如U+4??
)。
那么 Unicdoe 范圍或者說字符范圍 (字符集) 有什么用呢?可以用多個(gè)@font-face
規(guī)則和不同的 Unicode 范圍共同定義一個(gè)復(fù)合型字體。換句話說,可以在一個(gè)自定義字體中包含來自不同語言文字的多個(gè)字體的不同字形,也可以定義一個(gè)只包含某種字體常用或罕用字符的新字體。如果同一個(gè)新字體的多個(gè)@font-face
規(guī)則中的 Unicode 范圍有重合,那么最后定義的規(guī)則先匹配。
下面的規(guī)則會基于日文字體 MSMincho 和英文字體 Gentium 定義一個(gè)新字體 JapaneseWithGentium,其中拉丁字母的字形來自 Gentium 字體,其他字形來自 MSMincho。

利用@font-face
的層疊規(guī)則,還可以實(shí)現(xiàn)對字體的 "按需下載"。比如,在下面的例子,如果只需要拉丁字符的字形,UA 只會下載 DroidSans.woff。

ML3 規(guī)定,@font-face
指定的字體資源采用懶加載策略,即如果不用到,就不下載。樣式表里可以定義很多@font-face
,但 UA 必須只下載那些樣式規(guī)則中引用到的字體。有一個(gè)例外就是當(dāng)自定義字體作為后備字體時(shí),UA 可以提前下載,比如:

一般情況下,頁面都會先于字體加載完。此時(shí)使用自定義字體的文本應(yīng)該如何顯示呢?ML3 規(guī)定 UA 可以按照自定義字體不可用的情形來渲染字體,或者用后備字體將文本渲染為透明的。但在自定義字體下載失敗后,UA 必須顯示文本。因此,ML3 也要求樣式表作者指定與自定義字體大小類似的后備字體。
關(guān)于字體的獲取,ML3 規(guī)定必須使用啟用 CORS 的手段,使用Anonymous
模式,將referrer
設(shè)置為樣式表的 URL,將origin
設(shè)置為包含樣式表的文檔的 URL。
關(guān)于字體匹配,ML3 是有史以來最詳細(xì)的。它增加了font-stretch
的匹配,羅列出了font-style
所有可能的匹配情形。small-caps
完全從字體匹配流程中剝離,由字體特性來處理。要求必須使用 Unicode 變體選擇符。簇序列作為一個(gè)單位匹配。
字體特性
如前所述,font-variant
屬性一直以來只有一個(gè)small-caps
變體。而實(shí)踐中使用的字體遠(yuǎn)不止只有小型大寫字母一種變化形式。為此,ML3 擴(kuò)展了font-variant
屬性,使其成為了控制所有樣式相關(guān)字體特性的一個(gè)簡寫屬性。
換句話說,font-variant
有了font-variant-ligatures
、font-variant-postion
、font-variant-caps
、font-variant-numeric
、font-variant-east-asian
等具體屬性。
字體特性可以通過font-variant
或font-feature-settings
來啟用。具體細(xì)節(jié)因?yàn)樯婕坝⑽淖煮w的很多古老傳統(tǒng),有興趣的讀者可以自行學(xué)習(xí)。
尾聲
CSS Font Module Level 3 在 2018 年 9 月成為 W3C 推薦標(biāo)準(zhǔn),隨即又開始了 CSS Fonts Module Level 4,包含了一些 CSS 字體相關(guān)的試驗(yàn)性特性。另外,從 CSS Font Module Level 3 中獨(dú)立出去的 CSS Font Loading Module Level 3 已經(jīng)得到主流瀏覽器較新版本的支持。
了解更多,請點(diǎn)擊:https://www.bilibili.com/video/BV13b411g78D
作者:為之漫筆
鏈接:https://juejin.cn/post/6911149782446669838
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。