可變字型

可變字型是 OpenType 字型規範的一項演進,它允許將一種字型的多種變體整合到一個檔案中,而無需為每個寬度、字重或樣式都使用單獨的字型檔案。透過 CSS 和單個 @font-face 引用,就可以訪問指定字型檔案中包含的所有變體。本文將為你提供開始使用可變字型所需的所有知識。

備註:要在你的作業系統上使用可變字型,你需要確保它是最新的。例如,Linux 作業系統需要最新的 Linux FreeType 版本,而 macOS High Sierra (10.13) 之前的版本不支援可變字型。如果你的作業系統不是最新的,你將無法在網頁或 Firefox 開發者工具中使用可變字型。

可變字型:它們是什麼,以及有何不同

為了更好地理解可變字型的不同之處,有必要回顧一下非可變字型是什麼樣的,以及它們之間的比較。

標準(或靜態)字型

過去,一種字型(typeface)會作為多個獨立的字型檔案(font)來製作,每個字型檔案代表一種特定的寬度/字重/樣式組合。因此,你會為“Roboto Regular”、“Roboto Bold”和“Roboto Bold Italic”分別準備不同的檔案——這意味著你最終可能需要 20 或 30 個不同的字型檔案來表示一個完整的字型(對於一個包含不同寬度的大型字型,這個數字可能會是好幾倍)。

在這種情況下,要在網站上將一種字型用於正文的典型用途,你至少需要四個檔案:常規體、斜體、粗體和粗斜體。如果你想新增更多的字重,比如為標題新增更細的字重或為特別強調的內容新增更粗的字重,那就意味著需要更多的檔案。這會導致更多的 HTTP 請求和更多的資料下載(通常每個檔案約 20k 或更多)。

可變字型

使用可變字型,所有這些排列組合都可以包含在一個檔案中。這個檔案會比單個字型檔案大,但在大多數情況下,它比你可能為正文載入的 4 個檔案要小或者大小相當。選擇可變字型的優勢在於,你可以訪問所有可用的字重、寬度和樣式範圍,而不再受限於你之前需要單獨載入的那幾種。

這使得一些常見的排版技術成為可能,例如為不同大小的標題設定不同的字重以在各種尺寸下獲得更好的可讀性,或者為資料密集型的顯示使用稍窄的寬度。作為比較,在雜誌的排版系統中,通常會在整個出版物中使用 10-15 種甚至更多的不同字重和寬度組合——這提供的樣式範圍比目前在 Web 上典型的(或者說僅出於效能原因就可行的)要廣泛得多。

關於字型族、字重和變體的說明

你可能注意到,我們一直在討論為每個字重和樣式(即粗體、斜體和粗斜體)使用特定的字型檔案,而不是依賴瀏覽器來合成它們。原因是大多數字體對於較粗的字重和斜體都有非常具體的設計,這些設計通常包含完全不同的字元(例如,小寫字母“a”和“g”在斜體中通常有很大不同)。為了最準確地反映字型設計,並避免不同瀏覽器之間以及它們如何合成不同樣式時可能出現的差異,在使用非可變字型時,在需要的地方載入特定的字型檔案會更準確。

你可能還會發現,一些可變字型被分成兩個檔案:一個用於直立體及其所有變體,另一個包含斜體變體。這樣做有時是為了在不需要或不使用斜體的情況下減少總體檔案大小。在所有情況下,仍然可以將它們連結到一個共同的 font-family 名稱,這樣你就可以使用相同的 font-family 和適當的 font-style 來呼叫它們。

引入“變化軸”

新的可變字型格式的核心是變化軸的概念,它描述了字型設計中特定方面的允許變化範圍。因此,“字重軸”描述了字形可以有多細或多粗;“寬度軸”描述了它們可以有多窄或多寬;“斜體軸”描述了是否存在斜體字形,並且可以相應地開啟或關閉,等等。請注意,一個軸可以是一個範圍,也可以是一個二元選擇。字重可能範圍是 1–999,而斜體可能是 0 或 1(關閉或開啟)。

根據規範的定義,有兩種型別的軸:註冊軸自定義軸

  • 註冊軸是那些最常遇到的軸,其常見程度足以讓規範的作者們認為有必要將其標準化。目前已註冊的五個軸是字重、寬度、傾斜、斜體和視覺尺寸。W3C 已經著手將它們對映到現有的 CSS 屬性上,並且在一種情況下還引入了一個新的屬性,你將在下面看到。
  • 自定義軸是無限的:字型設計師可以定義和限定任何他們喜歡的軸,只需要給它一個四個字母的標籤,以便在字型檔案格式中識別它。你可以在 CSS 中使用這些四字母標籤來指定該變化軸上的一個點,如下面的程式碼示例所示。

註冊軸和現有的 CSS 屬性

在本節中,我們將透過示例和相應的 CSS 來演示定義的五個註冊軸。在可能的情況下,標準語法和底層語法都會包含在內。底層語法(font-variation-settings)是第一個為測試可變字型支援的早期實現而實現的機制,並且對於利用五個註冊軸之外的新軸或自定義軸是必需的。然而,W3C 的意圖是,當有其他屬性可用時,不應使用此語法。因此,只要有可能,就應該使用適當的屬性,只有在需要設定其他方式無法設定的值或軸時,才使用 font-variation-settings 的底層語法。

注意

  1. 使用 font-variation-settings 時,需要注意軸名稱是區分大小寫的。註冊軸名稱必須是小寫,而自定義軸必須是大寫。例如

    css
    font-variation-settings:
      "wght" 375,
      "GRAD" 88;
    

    wght(字重)是一個註冊軸,而 GRAD(等級)是一個自定義軸。

  2. 如果你已經使用 font-variation-settings 設定了值,並且想要更改其中一個值,你必須重新宣告所有這些值(就像使用 font-feature-settings 設定 OpenType 字型特性時一樣)。你可以透過使用 CSS 自定義屬性(CSS 變數)來為單個值設定,然後修改單個自定義屬性的值來解決這個限制。示例程式碼將在指南的末尾提供。

字重

字重(由 wght 標籤表示)定義了字形筆畫可以有多細或多粗(在典型排版術語中稱為 light 或 heavy)的設計軸。很長一段時間以來,CSS 已經可以透過 font-weight 屬性來指定這一點,該屬性接受從 100 到 900(以 100 為增量)的數值,以及像 normalbold 這樣的關鍵字,這些關鍵字是其相應數值的別名(在這種情況下是 400 和 700)。在處理非可變或可變字型時,這些仍然適用,但對於可變字型,現在任何從 1 到 1000 的數字都是有效的。

應該注意的是,目前在 @font-face 宣告中,沒有辦法將可變字型的變化軸上的特定點“對映”到關鍵字 bold(或任何其他關鍵字)。這通常可以相當容易地解決,但確實需要在編寫 CSS 時多一個步驟。

css
font-weight: 375;

font-variation-settings: "wght" 375;

點選下方程式碼塊中的“執行”來在 MDN Playground 中編輯示例。編輯 CSS 程式碼來體驗 font-weight 的值。

css
/* weight range is 300 to 900 */
.p1 {
  font-weight: 625;
}

/* weight range is 300 to 900 */
.p2 {
  font-variation-settings: "wght" 625;
}

/* Adjust with slider & custom property */
.p3 {
  font-variation-settings: "wght" var(--text-axis);
}

寬度

寬度(由 wdth 標籤表示)定義了字形可以有多窄或多寬(在排版術語中稱為 condensed 或 extended)的設計軸。這通常在 CSS 中使用 font-stretch 屬性來設定,其值表示為高於或低於“正常”(100%)的百分比,技術上任何大於 0 的數字都是有效的——儘管範圍更有可能接近 100% 標記,例如 75%-125%。如果提供的數值超出了字型中編碼的範圍,瀏覽器應該以允許的最接近的值來渲染字型。

備註:在使用 font-variation-settings 時不使用 % 符號。

css
font-stretch: 115%;

font-variation-settings: "wdth" 115;

點選下方程式碼塊中的“執行”來在 MDN Playground 中編輯示例。編輯 CSS 程式碼來體驗 font-width 的值。

css
/* width range is 55% to 100% */
.p1 {
  font-stretch: 60%;
}

/* width range is an integer from 55 to 100 */
.p2 {
  font-variation-settings: "wdth" 60;
}

/* Adjust with slider & custom property */
.p3 {
  font-variation-settings: "wdth" var(--text-axis);
}

斜體

斜體(ital)軸可以在 [0-1] 範圍內設定,其中 0 表示“非斜體”,0.5 表示“半斜體”,1 表示“完全斜體”。斜體設計通常包含與其直立體版本截然不同的字形,因此在從直立體到斜體的過渡中,通常會發生一些字形(或字元)替換。斜體(Italic)和偽斜體(oblique)通常被交替使用,但實際上它們有很大的不同。偽斜體在此上下文中用術語 slant(見下文)定義,一種字型通常只會有其中一種,而不會兩者都有。

在 CSS 中,斜體和偽斜體都使用 font-style 屬性應用於文字。另請注意引入了 font-synthesis: none;——這將防止瀏覽器意外地同時應用變化軸和合成的斜體。這也可以用來防止偽粗體。

css
font-style: italic;

font-variation-settings: "ital" 1;

font-synthesis: none;

點選下方程式碼塊中的“執行”來在 MDN Playground 中編輯示例。編輯 CSS 程式碼來體驗 font-italics。

css
/* font-style: italic, with and without font-synthesis */
.p1 {
  font-style: italic;
}

.p1-no-synthesis {
  font-style: italic;
  font-synthesis: none;
}

/* italic range is 0 or 1 */
.p2 {
  font-variation-settings: "ital" 1;
  font-synthesis: none;
}

/* Adjust with slider & custom property */
.p3 {
  font-synthesis: none;
  font-variation-settings: "ital" var(--text-axis);
}

傾斜

傾斜(由 slnt 標籤表示),或者通常被稱為“偽斜體”(oblique)——與真正的斜體不同,它改變了字形的角度,但不會進行任何字元替換。它也是可變的,因為它以數值範圍表示。這使得字型可以在傾斜軸上的任何位置變化。允許的範圍是從 -90 到 90 度。

可以控制傾斜的兩個屬性是 font-stylefont-variation-settings。以下兩個屬性宣告是相同的

font-style: oblique 14deg;

font-variation-settings: "slnt" -14;

優先使用 font-style 屬性,而不是 font-variation-settings 屬性。使用 font-variation-settings 屬性時,不使用 deg 關鍵字。此外,對於 font-variation-settings 屬性,正角度表示逆時針傾斜。

在下面的即時示例中,你可以調整傾斜度。

css
.font-style {
  font-style: oblique 5deg;
}

.font-variation {
  font-variation-settings: "slnt" -5;
}

.adjustable {
  font-variation-settings: "slnt" var(--slant-angle);
}

視覺尺寸

這對於數字字型和 CSS 來說是新事物,但在設計和製作金屬活字方面,這是一項有數百年曆史的技術。視覺尺寸調整(Optical sizing)是指根據物理尺寸改變字形整體筆畫粗細的做法。如果尺寸非常小(例如相當於 10 或 12px),字元的整體筆畫會更粗,並且可能還有其他一些小的修改,以確保它在物理上更小的尺寸下能夠重現並可讀。相反,當使用更大的尺寸時(比如 48 或 60px),粗細筆畫之間可能會有更大的變化,從而更符合原始意圖地展示字型設計。

雖然這最初是為了補償油墨和紙張的印刷過程(小尺寸下非常細的線條通常無法印刷出來,導致字形看起來不完整),但它在補償螢幕質量和物理尺寸渲染時,同樣適用於數字顯示。

視覺尺寸值通常旨在根據 font-size 自動應用,但也可以使用底層的 font-variation-settings 語法來操縱。

為了在 CSS 中支援可變字型,建立了一個新屬性 font-optical-sizing。當使用 font-optical-sizing 時,唯一允許的值是 autonone——所以這個屬性只允許開啟或關閉視覺尺寸調整。然而,當使用 font-variation-settings: 'opsz' <num> 時,你可以提供一個數值。在大多數情況下,你會希望將 font-size(字型被渲染的物理尺寸)與 opsz 值(這是使用 auto 時視覺尺寸調整的預期應用方式)相匹配。提供指定特定值的選項是為了在需要覆蓋預設值時——無論是出於易讀性、美學還是其他原因——可以應用一個特定的值。

css
font-optical-sizing: auto;

font-variation-settings: "opsz" 36;

點選下方程式碼塊中的“執行”來在 MDN Playground 中編輯示例。編輯 CSS 程式碼來體驗視覺尺寸的值。

css
.p1 {
  font-optical-sizing: none;
}
/* font-optical-sizing can be auto or none */
.p2 {
  font-optical-sizing: auto;
}

/* optical range is from 8 to 144 */
.p3 {
  font-variation-settings: "opsz" 64;
}

/* Adjust with slider & custom property */
.p4 {
  font-variation-settings: "opsz" var(--text-axis);
}

自定義軸

自定義軸正如其名:它們可以是字型設計師想象的任何設計變化軸。可能會有一些變得相當普遍——甚至成為註冊軸——但這隻有時間才能證明。

等級

等級(Grade)可能會成為更常見的自定義軸之一,因為它在字型設計中有已知的歷史。設計不同等級的字型的做法通常是為了應對預期的用途和印刷技術。“等級”這個術語指的是字型設計的相對粗細或密度,但與傳統的“字重”不同之處在於,文字所佔的物理空間不會改變,因此改變文字等級不會改變文字的整體佈局或其周圍的元素。這使得等級成為一個有用的變化軸,因為它可以被改變或動畫化,而不會導致文字本身的迴流。

css
font-variation-settings: "GRAD" 88;

點選下方程式碼塊中的“執行”來在 MDN Playground 中編輯示例。編輯 CSS 程式碼來體驗 font-grade 的值。

css
/* grade range is 88 to 150 */
.p1 {
  font-size: 64px;
  font-variation-settings: "GRAD" 88;
}

/* Adjust with slider & custom property */
.p2 {
  font-size: 64px;
  font-variation-settings: "GRAD" var(--text-axis);
}

使用可變字型:@font-face 的變化

載入可變字型的語法與任何其他網路字型非常相似,但有一些顯著的區別,這些區別是透過對傳統 @font-face 語法的升級提供的,現在在現代瀏覽器中可用。

基本語法是相同的,但可以指定字型技術,並且可以為像 font-weightfont-stretch 這樣的描述符提供允許的範圍,而不是根據載入的字型檔案來命名。

標準直立體(Roman)字型的示例

css
@font-face {
  font-family: "MyVariableFontName";
  src: url("path/to/font/file/my-variable-font.woff2")
    format("woff2-variations");
  font-weight: 125 950;
  font-stretch: 75% 125%;

  font-style: normal;
}

在這種情況下,font-style: normal 宣告表示當 font-family 設定為 MyVariableFontName 並且 font-style 設定為 normal 時,應使用此字型檔案。作為替代方案,你可以使用 font-style: oblique 0degfont-style: oblique 0deg 20deg 來表示字型具有正常的直立字形(由 0deg 表示)。

僅包含斜體而不包含直立字元的字型示例

css
@font-face {
  font-family: "MyVariableFontName";
  src: url("path/to/font/file/my-variable-font.woff2")
    format("woff2-variations");
  font-weight: 125 950;
  font-stretch: 75% 125%;

  font-style: italic;
}

在這種情況下,font-style: italic 宣告表示當 font-family 設定為 MyVariableFontName 並且 font-style 設定為 italic 時,應使用此字型檔案。作為替代方案,你可以使用 font-style: oblique 14deg 來表示字型具有斜體字形。

包含偽斜體(傾斜)軸的字型示例

css
@font-face {
  font-family: "MyVariableFontName";
  src: url("path/to/font/file/my-variable-font.woff2")
    format("woff2-variations");
  font-weight: 125 950;
  font-stretch: 75% 125%;

  font-style: oblique 0deg 12deg;
}

在這種情況下,oblique 0deg 12deg 值表示當樣式規則中 font-family 屬性為 MyVariableFontName 並且 font-style 屬性為 oblique 且角度在 0 到 12 度之間(含)時,應使用此字型檔案。

備註:並非所有瀏覽器都實現了字型格式的完整語法,因此請仔細測試。所有支援可變字型的瀏覽器,如果你將格式設定為僅檔案格式,而不是 format-variations(即使用 woff2 而不是 woff2-variations),它們仍然會渲染字型,但如果可能的話,最好使用正確的語法。

備註:font-weightfont-stretchfont-style 提供值範圍將防止瀏覽器在您使用適當的屬性(即 font-weightfont-stretch)時嘗試渲染超出該範圍的軸,但不會阻止您透過 font-variation-settings 提供無效值,因此請謹慎使用。

處理舊版瀏覽器

可變字型的支援可以透過 CSS 特性查詢(參見 @supports)來檢查,因此可以在生產環境中使用可變字型,並將呼叫可變字型的 CSS 範圍限定在一個特性查詢塊內。

css
h1 {
  font-family: some-non-variable-font-family;
}

@supports (font-variation-settings: "wdth" 115) {
  h1 {
    font-family: some-variable-font-family;
  }
}

示例頁面

以下示例頁面展示了兩種不同的 CSS 結構方式。第一個示例儘可能使用標準屬性。第二個示例使用 CSS 自定義屬性為 font-variation-settings 字串設定值,並展示瞭如何透過覆蓋單個變數而不是重寫整個字串來更輕鬆地更新單個變數值。注意 h2 上的懸停效果,它只改變了等級軸的自定義屬性值。點選下方程式碼塊中的“執行”來在 MDN Playground 中編輯示例。

css
.container1 h1 {
  font-optical-sizing: auto;
  font-size: 5rem;
  font-stretch: 85%;
  font-weight: 450;
}
.container1 h2 {
  font-optical-sizing: auto;
  font-size: 2.25rem;
  font-stretch: 90%;
  font-weight: 575;
}
.container1 p {
  font-optical-sizing: auto;
  font-size: 1rem;
  font-stretch: 100%;
  font-weight: 375;
}
.demo2 {
  --text-wght: 375;
  --text-wdth: 100;
  --text-opsz: 16;
  --text-GRAD: 88;
}
.container2 > * {
  font-size: 5rem;
  font-variation-settings:
    "wght" var(--text-wght),
    "wdth" var(--text-wdth),
    "opsz" var(--text-opsz),
    "GRAD" var(--text-GRAD);
}
.container2 h1 {
  --text-wght: 450;
  --text-wdth: 85;
  --text-opsz: 80;
  font-size: 5rem;
}
.container2 h2 {
  --text-wght: 575;
  --text-wdth: 95;
  --text-opsz: 36;
  font-size: 2.25rem;
}
.container2 h2:hover {
  --text-GRAD: 130;
}
.container2 p {
  font-size: 1rem;
}

資源