CSS字體,從Level 1到Level 3

2021-02-16 奇舞精選

編者按:本文作者李松峰,資深技術圖書譯者,翻譯出版過40餘部技術及互動設計專著,現任360奇舞團Web前端開發資深專家,360前端技術委員會委員、W3C AC代表。

本文是閱讀CSS標準文檔的筆記,也是對CSS字體相關知識的一個梳理。

Cascading Style Sheets, level 1

CSS 1定義的字體屬性包括:font-family、font-style、font-variant、font-weight、font-size和font。其算法要求UA(User Agent,用戶代理)對給定元素中的字符逐個查找匹配的CSS屬性,首先嘗試匹配font-style,比如italic和oblique。然後匹配font-variant,normal匹配非small-caps(小型大寫)字體,而small-caps則匹配 (1)標識為small-caps的字體 (2)合成小型大寫字母的字體 (3)將小寫字母替換為大寫字母的字體(小型大寫字母可以通過將normal字體的大寫字母縮小來實現)。接著匹配font-weight和font-size,這兩個屬性都是必須匹配成功的。

font-family是一個按照優先級排列的字體或通用字體名字的列表,每個名字以逗號分隔,表示多選一。

body { font-family: gill, helvetica, sans-serif; }

有兩種值:字體名和通用字體名。在上面的例子中,gill和helvetica就是明確指定的字體名,而sans-serif則是通用字體名。CSS 1定義了5種通用字體:

serif:襯線

sans-serif:非襯線

cursive:手寫

fantasy:裝飾

monospace:等寬

通常,除了指定特定的字體名,最後都應該指定一個通用字體名。另外,如果字體名包含空格,必須用引號括起來。

font-style有3個值: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字體中的大寫字母縮小後代替。實在不行,也可以直接用大寫字母。

CSS 1只支持small-caps一種變體,不支持老式數字、小型大寫數字、緊縮或疏鬆字母等其他變體。

font-weight選擇字重,有關鍵字值normal、bold、bolder、lighter和數值100~900,表示筆畫越來越粗。normal對應400,bold對應700。bolder和lighter則相對於從父元素繼承的字重加粗或變細。現實中的字體(字體數據)都會有一個或幾個屬性的值用於描述字體的"重量"。但不同字體使用的屬性值並不統一,比如包含以下關鍵字的值似乎都可以認為是粗體:Regular、Roman、Book、Medium、Semi-、DemiBold、Bold或Black,具體要看其normal字形有多重。正因為如此,CSS 1才定義了一系列數值。OpenType使用9個數值區分字重,可以直接對應。但並非所有字體都有那麼多字重,CSS 1為此也定義了如何向前或向後"尋值",比如500如果沒有,則用400。

font-size定義了絕對值、相對值、長度值和百分比值。絕對值包括xx-small、x-small、small、medium、large、x-large和xx-large等關鍵字,它們在UA裡以1.5倍的比例差異保存著絕對大小。相對值有larger和smaller關鍵字,取決於父元素文本大小的絕對值。不允許負值。

最後,font是以上所有屬性的簡寫屬性,可以同時設置font-style、font-variant、font-weight、font-size、line-height和font-family。這個屬性借鑑了傳統排版中的同時設置多個屬性的簡寫法。

Cascading Style Sheets Level 2 Revision 1

CSS 1奠定了字體屬性的格局。CSS 2.1僅對CSS 1進行了補充和擴展。

首先,CSS 1隻規定font-family最後要使用一種通用字體作為後備,並沒有詳細說明這些字體的特點和舉例。CSS 2.1則詳細解讀了serif、sans-serif、cursive、fantasy和monospace。

其次,對所有屬性統一增加了inherit關鍵字。而且,font-variant仍然只支持small-caps一種變體形式。

最後,CSS 2.1比較重要的一個增補,是為font簡寫屬性增加了6種系統字體關鍵字:caption、icon、menu、message-box、small-caption和status-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-family和src是必需的描述符。(注意,在普通CSS聲明裡,font-family和src是屬性,而在@font-face規則裡,因為是用於定義新字體,所以font-family和src就成了描述符,即用於描述新字體的屬性。)

font-family描述符定義字體名字,會覆蓋底層字體文件中的名字,而且如果名字跟系統字體衝突,還會覆蓋系統字體。

src描述符定義字體的來源,其值為按優先次序排列的來源列表,來源本地使用local()引入,來源外部使用url()引入。使用url()引入外部字體時,可以用format()添加字體格式的提示。ML3定義的有效字體格式字符串有:

格式字符串字體格式常見擴展名"woff"WOFF 1.0 (Web Open Font Format).woff"woff2"WOFF 2.0 (Web Open Font Format).woff2"truetype"TrueType.ttf"opentype"OpenType.ttf, .otf"embedded-opentype"Embedded OpenType.eot"svg"SVG Font.svg, .svgz

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

@font-face {

  font-family: bodytext;

  src: url(ideal-sans-serif.woff2) format("woff2"),

       url(good-sans-serif.woff) format("woff"),

       url(basic-sans-serif.ttf) format("opentype");

}

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

@font-face {

  font-family: MyGentium;

  src: local(Gentium Bold), 

       local(Gentium-Bold), 

       url(GentiumBold.woff); 

  font-weight: bold;

}

local()函數很有用,比如上面的例子其實是為不同平臺下的同一款字體創建了一個統一的別名。再比如下面的例子,用於將一種大字體中永遠都不會被引用到的字體抽取出來:

@font-face {

  font-family: Hoefler Text Ornaments;

  

  src: local(HoeflerText-Ornaments);

}

另外,ML3規定UA只能優先使用字體文件中的英文全名來匹配字體。即便用戶作業系統將地區設置為比如德國、芬蘭,而字體文件中也有德語、芬蘭語的字體全名,也要匹配英文全名,這是為了全平臺統一起見。因此下面h2最終會使用默認的襯線字體:

@font-face {

  font-family: SectionHeader;

  src: local("Arial Lihavoitu"); 

  font-weight: bold;

}

h2 { font-family: SectionHeader, serif; }

最後,如果存在多個src描述符,後聲明的會覆蓋先聲明的:

@font-face {

  font-family: MainText;

  src: url(gentium.eot); 

  src: local("Gentium"), url(gentium.woff); 

}

font-style、font-weight和font-stretch這三個描述符的值跟對應屬性的值一樣,只是不允許使用相對關鍵字bolder和lighter。

綜上所述,@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 {

  font-family: JapaneseWithGentium;

  src: local(MSMincho);

  

}

@font-face {

  font-family: JapaneseWithGentium;

  src: url(../fonts/Gentium.woff);

  unicode-range: U+0-2FF;

  

}

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

@font-face {

  font-family: DroidSans;

  src: url(DroidSansFallback.woff);

  

}

@font-face {

  font-family: DroidSans;

  src: url(DroidSansJapanese.woff);

  unicode-range: U+3000-9FFF, U+ff??;

}

@font-face {

  font-family: DroidSans;

  src: url(DroidSans.woff);

  unicode-range: U+000-5FF, U+1e00-1fff, U+2000-2300;

}

ML3規定,@font-face指定的字體資源採用懶加載策略,即如果不用到,就不下載。樣式表裡可以定義很多@font-face,但UA必須只下載那些樣式規則中引用到的字體。有一個例外就是當自定義字體作為後備字體時,UA可以提前下載,比如:

@font-face {

  

  font-family: GeometricModern;

  src: url(font.woff);

}

p {

  

  font-family: GeometricModern, sans-serif;

}

h2 {

  

  font-family: Futura, GeometricModern, sans-serif;

}

一般情況下,頁面都會先於字體加載完。此時使用自定義字體的文本應該如何顯示呢?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-ligatures、font-variant-postion、font-variant-caps、font-variant-numeric、font-variant-east-asian等具體屬性。

字體特性可以通過font-variant或font-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已經得到主流瀏覽器較新版本的支持。

相關連結

Cascading Style Sheets, level 1(https://www.w3.org/TR/REC-CSS1/)

Cascading Style Sheets Level 2 Revision 1 (CSS 2.1)(https://www.w3.org/TR/2011/REC-CSS2-20110607/)

CSS Font Module Level 3(https://drafts.csswg.org/css-fonts-3/)

CSS Fonts Module Level 4(https://drafts.csswg.org/css-fonts-4/)

CSS Font Loading Module Level 3(https://drafts.csswg.org/css-font-loading-3/)

Character Model for the World Wide Web 1.0: Fundamentals:(https://www.w3.org/TR/2005/REC-charmod-20050215/)

關於奇舞周刊

《奇舞周刊》是360公司專業前端團隊「奇舞團」運營的前端技術社區。關注公眾號後,直接發送連結到後臺即可給我們投稿。

相關焦點

  • 紐西蘭從lockdown,到level 3,再到level 2
    自從紐西蘭lockdown,再降到level 3以來,每天只能三點一線了,即工作地點——超市——家裡。 先說說超市的一些改變吧,超市配置一個工作人員用消毒水處理用過的購物車,以給另一個shopper使用,因為這邊比較注重勤洗手,避免接觸病毒。
  • 18年 CFA level1 和 level2 考試大綱配比詳情
    CFA level1 的考試  6個小時 上午 3小時 下午3小時Morning session (3 hours): 120 multiple choice questions, covering all topicsAfternoon session (3 hours): 120 multiple choice
  • CSS的字體和排版
    字體當你寫代碼的時候,可以用「monospace」字體;So cursive is meant to be handwritten style of fonts. cursive:手寫體;fantasy:外星字體;如果你看過cssfontstack.com網站[3],你會發現有人很用心地列出了所有這些區分常用字體的比例
  • 中國大陸學生等級從Level 2調回Level 1!
    澳大利亞籤證風險等級2020年3月26日更新:China: Level 1Hong Kong: Level 1Taiwan: Level 1IndonesiaBangladesh: Level 2Nepal: Level 3India: Level 3Pakistan: Level 3Bhutan: Level 3什麼是
  • LOD到底是Level of Development還是Level of Detail?
    The idea was that the word 「detail」 would be interpreted as graphicaldetail, but 「development」 referred to the level ofcertainty about an object on mode than a graphical level.
  • A level 選3門們還是4門呢?
    我的A level選了3門,我的小夥伴選了4門?這有什麼去別的,會影響我的目標院校對我的評估嗎?學4門A-level的幾種情況1.學習進階數學作為第四門A-level。因為通常進階數學是基於A-level數學水平的學習,二者經常成對出現,如果只學習3個科目,其中兩門是數學,未來大學專業的選擇面未免太窄了,所以這樣的同學常常會學習4門A-level。一般大學申請目標專業數學、計算機、工程或物理的學生,會學習4門A-level。2.也有少部分學生學習數學和三門科學A-level。
  • Level-headed?
    , 2018): Most Americans believe Trump is not fit to be president - with seven in 10 saying he is not level-headed.
  • ...交易所level 1和level 2行情數據以及tick數據都是什麼意思?
    今天我們就來看一下level 1和level 2行情數據以及tick數據這些術語所代表的信息。tick行情和快照行情tick行情又稱逐筆行情,是整個市場上的逐筆數據。例如投資者一筆新的委託會形成一筆行情,交易所撮合一筆新的成交也會形成一筆行情。
  • 英國高中 A-level,十問十答
    英國雖然沒有高考,A-level成績可近似理解為「英國高考成績」,但是你知道A-level嗎?1. 什麼是A-level?簡言之,A-level可近似理解為「英國高中」,A-level成績可近似理解為「英國高考成績」。2.A-level的學制是怎樣的? 兩年。第一年,學生選擇自己擅長且感興趣的4門課,通過考試後獲得AS證書。第二年,學生可選擇第一年成績較為優秀的3門課程繼續學習,通過考試後獲得A-Level證書。
  • .| 交易所level 1和level 2行情數據以及tick數據都是什麼意思?
    今天我們就來看一下level 1和level 2行情數據以及tick數據這些術語所代表的信息。level1行情和level2行情level1行情又稱1檔行情或基本行情,字面意義上是指行情報單簿的檔位只有一檔,即買一價,賣一價。實際應用中一般用來指比較基礎的一種行情,只包含最低層次的買賣,成交數據,更新頻次也是最低。
  • 什麼是A-LEVEL?
    通常國內A-level招收的是高一或高二畢業的學生,並要求參加相關的入學考試。英國高中課程(A-Level)的學制為兩年:第一年稱為AS水準,學生通常選擇自己最擅長且最有興趣的3—4門課,通過考試後獲得AS證書。第二年稱為A2水準,學生可選擇AS水準中優秀的3門課繼續學習,通過考試後獲得A-Level證書。
  • level best 是最好程度?on the level 指同一個水平?都不對!
    老闆覺得這事好到不可思議,就問他:「It seems too good to be true. Are you sure it is on the level?」Michael覺得很納悶,Level?老闆難道是在問對方的程度嗎?其實 on the level 和你想的不一樣。
  • level best 是最好程度?on the level 指同一個水平?都不對
    老闆覺得這事好到不可思議,就問他:「It seems too good to be true. Are you sure it is on the level?」Michael覺得很納悶,Level?老闆難道是在問對方的程度嗎?其實 on the level 和你想的不一樣。今天來看看 level 這個字的道地用法。
  • A-level成績先降後調,上萬A-Level考生真沒學上?
    每年8月中下旬英國A-level放榜日,總是幾家歡喜幾家愁。今年更是一波未平一波又起: 受疫情影響,英國取消A- level考試,成績評定改為算法打分,以至將近40%的英格蘭地區A-level考生成績被下調,引發了學生及家長的強烈不滿。
  • A-Level學校火到爆?8所廣州最具代表性A-Level學校大盤點!
    3適合學生A-level相對而言總體難度低一些,因為只需要學習三到四科自己感興趣和就讀大學對口的課程,同時也不強制要求參加很多課外活動等,但單科難度並不低。如果孩子學習成績不是很好,偏科嚴重,希望能申請到一個好一點的本科、成為特色鮮明的個性人才,那麼建議學習A-Level課程。
  • A-Level是什麼課程?如何學好A-Level的數學、物理、化學等課程?
    A-Level課程,是英國的普通中等教育證書考試高級水平課程,是目前世界上最為廣泛採用的基礎教育體制,全球現有160多個國家的11000多所正規大學所認可A-level課程,每年有500多萬學生參加A-level考試,學生憑證書可直接進入各國大學的大學一年級學習(包括劍橋、牛津、哈佛
  • A-level考試成績放榜,用A-level分數申請英美加澳大學有何異同?
    A-level考試和申請英美加澳本科的關係1、申請英國本科學生為主,錄取率平均在20.3%,5個學生裡就有1個能錄到劍橋本科。3、申請加拿大本科A-level體系學生申請加拿大大學,一般要求>IGCSE 5門課、AS 4門課和A2 3門課,以及雅思或託福,還有文書。
  • A-level經濟學習常見問題解答
    這意味著year 1你將學習到絕大部分內容,然後第二年預留出時間複習和深化。通常第二年難度高於第一年學習。A-level經濟尤其如此,第二年要求你把知識實實在在運用到不同的情況中進行分析。A-level經濟其實內容也沒有多到可怕,只要充分理解,就基本ok。A-level經濟內容難度如何?A-level經濟其實沒有那麼難。大多數內容是不言自明的,而且稍微關注一點常識,會讓你的學習更順利。
  • 一文縱覽最全A-level學習手冊!附上海A-level國際學校大盤點
    今天先來說說A-level,本文主要內容包括:1、A-level基本科普2、A-level選課搭配3、A-level計算方式4、A-level學習規劃4、A-level國際學校2分鐘科普A-level課程A-Level課程是英國普通中等教育證書高級水平課程,英國學生的大學入學考試課
  • CSS 字體新玩法之彩色字體
    字體模塊標準的現狀CSS Fonts Module Level 3 2 :目前處於候選推薦狀態,是主流瀏覽器都已大部分實現的標準,最新一版候選標準發表於今年的 6 月 26 日。Level 3 標準基於之前的 CSS3 Fonts 以及 CSS3 Web Fonts,並將字體加載事件相關的標準移入 CSS Font Loading 3模塊中。