改善備用字型

Katie Hempenius
Katie Hempenius

摘要

本文將深入介紹字型備用選項,以及 size-adjustascent-overridedescent-overrideline-gap-override API。這些 API 可以使用本機字型建立與網頁字型尺寸密切或完全相符的備用字型。這樣可以減少或消除字型替換造成的版面配置位移。

如果您想略過本文,可立即使用這些 API 來開始使用:

架構工具:

  • @next/font:自 10 月 13 日起,next/font 會自動使用字型指標覆寫功能和 size-adjust 來提供相符的字型備用選項。
  • @nuxtjs/fontaine:從 Nuxt 3 開始,您可以使用 nuxt/fontaine 自動產生相符的字型,並在 Nuxt 應用程式使用的樣式表中插入。

非架構工具:

  • Fontaine:Fontaine 這個程式庫會自動產生及插入使用字型指標覆寫功能的字型備用。
  • 這個存放區包含 Google Fonts 代管所有字型的字型指標覆寫功能。您可以複製這些值並貼到樣式表中。

背景

備用字型是一種字型,可供系統尚未載入主要字型,或缺少轉譯網頁內容所需的字符時使用。舉例來說,下列 CSS 表示應使用 sans-serif 字型系列做為 "Roboto" 的字型備用。

font-family: "Roboto" , sans-serif;

備用字型可用於更快速地轉譯文字 (也就是使用 font-display: swap)。因此,網頁內容較早易讀且實用;但過去,這也會導致版面配置的不穩定問題,常常是因為網頁字型更換備用字型。不過,下方討論的新 API 可讓您建立備用字型,且佔用的空間大小與網路字型不同,因此可減少或解決這項問題。

改善備用字型

您可以透過兩種方式產生「改良」的字型備用內容。較簡單的做法只會使用字型指標覆寫 API。較複雜 (但功能更強大) 的方法會使用字型指標覆寫 API 和 size-adjust。本文將說明這兩種方法。

字型指標覆寫的運作方式

簡介

字型指標覆寫功能可讓您覆寫字型的上升、下降和行距:

  • 重音是指字型的字符從基準線所延伸的最遠距離。
  • 平穩:測量字型字符延伸到基準線以下的最遠距離。
  • 行距也稱為「領先」可評估連續文字行之間的距離。

這張圖表顯示字型的上升、下降和線段間距。

字型指標覆寫功能可用來覆寫備用字型的上升、下降和行距,以符合網路字型的上升、下降和行距。因此,網路字型和調整過的備用字型會一律套用相同的垂直尺寸。

字型指標覆寫功能可在樣式表中使用,如下所示:

body {
    font-family: Poppins, "fallback for poppins";
}

@font-face {
    font-family: "fallback for poppins";
    src: local("Times New Roman");
    ascent-override: 105%;
    descent-override: 35%;
    line-gap-override: 10%;
}

本文開頭列出的工具可產生正確的字型指標覆寫值。不過,您也可以自行計算這些值。

計算字型指標覆寫值

以下公式可產生指定網路字型的字型指標覆寫值。字型指標覆寫的值應以百分比 (例如 105%) 寫成,而非小數。

ascent-override = ascent/unitsPerEm
descent-override = descent/unitsPerEm
line-gap-override = line-gap/unitsPerEm

舉例來說,以下是 Poppins 字型的字型指標覆寫內容:

/*
Poppins font metrics:
ascent = 1050
descent = 350
line-gap = 100
UPM: 1000
*/

ascent-override: 105%;  /* = 1050/1000 */
descent-override: 35%;  /* = 350/1000 */
line-gap-override: 10%; /* = 100/1000 */

ascentdescentline-gapunitsPerEm 的值皆來自網路字型的中繼資料。本文下一節將說明如何取得這些值。

讀取字型表格

字型的中繼資料 (尤其是字型表格) 包含計算字型指標覆寫值所需的所有資訊。

FontForge 中字型資訊對話方塊的螢幕截圖。對話方塊會顯示字型指標,例如「Typo Ascent」、「Typo Descent」和「Typo Line Gap」。
使用 FontForge 查看字型中繼資料

你可以使用以下工具讀取字型中繼資料:

  • fontkit 是專為 Node.js 打造的字型引擎,此程式碼片段說明如何使用 fontkit 計算字型指標覆寫值。
  • 「Capsize」是字型大小和版面配置程式庫。Capsize 提供的 API 可用於取得各種字型指標的相關資訊。
  • fontdrop.info 是一種網站,可讓你在瀏覽器中查看字型表和其他字型相關資訊。
  • Font Forge 是熱門的電腦版字型編輯器。如要查看 ascentdescentline-gap:請開啟 Font Info 對話方塊,然後依序選取 OS/2 選單和「Metrics」分頁標籤。如要查看 UPM:開啟 Font Info 對話方塊,然後選取 General 選單。

瞭解字型表格

您可能會注意到,「密集」這類概念是由多個指標所指稱,例如 hheaAscenttypoAscentwinAscent 指標。這是因為各種作業系統採用不同的字型轉譯方法:OSX 裝置上的程式通常會使用 hhea* 字型指標,而 Windows 裝置上的程式通常會使用 typo* (也稱為 sTypo*) 或 win* 字型指標。

系統會根據字型、瀏覽器和作業系統,使用 hheatypowin 指標顯示字型。

Mac Windows
Chromium 使用「hhea」資料表中的指標。 如果已設定「USE_TYPO_METRICS」,則使用「typo」資料表中的指標,否則會使用「win」資料表的指標。
Firefox 如果已設定「USE_TYPO_METRICS」,則使用「typo」資料表中的指標,否則會使用「hhea」資料表中的指標。 如果已設定「USE_TYPO_METRICS」,則使用「typo」資料表中的指標,否則會使用「win」資料表的指標。
Safari 使用「hhea」資料表中的指標。 如果已設定「USE_TYPO_METRICS」,則使用「typo」資料表中的指標,否則會使用「win」資料表的指標。

如要進一步瞭解字型指標在不同作業系統中的運作方式,請參閱這篇文章,瞭解垂直指標。

跨裝置相容性

對絕大多數字型 (例如 Google Fonts 代管的字型約 90%) 中,字型指標覆寫功能無需瞭解使用者的作業系統,即使不瞭解使用者的作業系統,ascent-overridedescent-overridelinegap-override 的值也都會保持不變,無論是否套用 hheatypowin 指標都一樣。這個存放區提供適用和不適用字型的相關資訊。

如果您採用的字型需要針對 OSX 和 Windows 裝置使用個別的字型指標覆寫,請使用字型指標覆寫功能。除非您能根據使用者的作業系統變更樣式表,否則我們不建議使用 size-adjust

使用字型指標覆寫功能

由於字型指標覆寫的資料是取自網路字型中繼資料 (而非備用字型) 的測量結果,因此無論使用哪一種字型,它們都會保持不變。例如:

body {
  font-family: "Poppins", "fallback for Poppins", "another fallback for Poppins";
}

@font-face {
  font-family: "fallback for Poppins";
  src: local("Arial");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

@font-face {
  font-family: "another fallback for Poppins";
  src: local("Roboto");
  ascent-override: 105%;
  descent-override: 35%;
  line-gap-override: 10%;
}

大小調整的運作方式

簡介

size-adjust CSS 描述元會按比例縮放字型字符的寬度和高度。舉例來說,size-adjust: 200% 會將字型字符縮放為原始大小的兩倍,size-adjust: 50% 會將字型字符縮放為原始大小的一半。

這張圖表顯示使用「size-Adjust: 50%」和「size-Adjust: 200%」後的結果。

由於 size-adjust 本身並未提供改善字型備用功能的應用程式,在大多數情況下,備用字型必須縮小或縮小 (而非按比例縮放),才能符合網路字型。不過,結合 size-adjust 與字型指標覆寫值,就可以讓任兩個字型在水平和垂直方向上互相比對。

以下是在樣式表中使用 size-adjust 的方式:

@font-face {
  font-family: "fallback for poppins";
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

基於 size-adjust 的計算方式 (將於下一節說明),size-adjust 的值 (以及對應的字型指標覆寫) 會視使用的備用字型而定:

body {
  font-family: "Poppins", "fallback for Poppins", "another fallback for Poppins";
}

@font-face {
  font-family: poppins-fallback;
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

@font-face {
  font-family: poppins-fallback-android;
  src: local("Roboto");
  size-adjust: 55.5193474%:
  ascent-override: 180.1173909%;
  descent-override: 63.04108683%;
  line-gap-override: 18.01173909%;
}

計算大小調整和字型指標覆寫值

以下是計算 size-adjust 和字型指標覆寫值的方程式:

size-adjust = avgCharacterWidth of web font / avgCharacterWidth of fallback font
ascent-override = web font ascent / (web font UPM * size-adjust)
descent-override = web font descent / (web font UPM * size-adjust)
line-gap-override = web font line-gap / (web font UPM * size-adjust)

這些輸入內容 (遞增、下降和行距) 大多可以直接從網路字型的中繼資料讀取,不過,avgCharacterWidth 需要約略值。

近似平均字元寬度

一般而言,平均字元寬度只提供約略值,但在某些情況下,可以精確計算此值,例如使用單寬字型,或是已事先得知文字字串內容時。

計算 avgCharacterWidth 的基本方法之一,就是取得所有 [a-z\s] 字元的平均寬度。

 比較個別 Roboto [a-zs] 字符的寬度的圖表。
Roboto 字符的寬度

不過,若設定所有字元的權重相等,可能會導致常用字母 (例如 e) 的寬度變小,不常使用的字母 (例如 z) 的寬度則過重。

想要提升準確度,還有一種更複雜的做法是將「字母頻率」納入考量,改為計算「頻率加權平均寬度」([a-z\s] 個字元)。這篇文章很適合參考英文文字的字母頻率和平均字詞長度。

顯示英文字母頻率的圖表。
英文的字母頻率

選擇方法

本文所討論的兩種方法各有優缺點:

  • 如果您剛開始對字型備用項目進行最佳化時,自行使用字型指標覆寫功能是不錯的方法。雖然這是一種更簡單的方法,但通常功能可以顯著降低與字型相關的版面配置位移幅度。

  • 另一方面,如果您想提高精確度,且願意執行一些工作和測試,加入 size-adjust 是不錯的做法。在正確實作的情況下,此方法可有效消除與字型相關的版面配置位移。

選擇備用字型

本文所述的技巧是使用字型指標覆寫和 size-adjust 來轉換廣泛提供的本機字型,而不是嘗試尋找近似於網路字型的本機字型。選擇本機字型時,請務必記住,少數字型普遍使用本機字型,而且所有裝置都沒有單一字型。

建議使用 Arial 做為 Sans Serif 字型的備用字型,而 Times New Roman 則是 Serif 字型的建議備用字型。不過,這些字型不適用於 Android (Android 上只有 Roboto 的系統字型)。

以下範例使用三種備用字型來確保裝置廣泛的覆蓋範圍:指定 Windows/Mac 裝置的備用字型、指定 Android 裝置的備用字型,以及使用一般字型系列的備用字型。

body {
  font-family: "Poppins", poppins-fallback, poppins-fallback-android, sans-serif;
}

/*
Poppins font metrics:
- ascent = 1050
- descent = 350
- line-gap = 100
- UPM: 1000
AvgCharWidth:
- Poppins: 538.0103768
- Arial: 884.1438804
- Roboto: 969.0502537
*/

@font-face {
  font-family: poppins-fallback;
  src: local("Arial");
  size-adjust: 60.85099821%;
  ascent-override: 164.3358416%;
  descent-override: 57.51754455%;
  line-gap-override: 16.43358416%;
}

@font-face {
  font-family: poppins-fallback-android;
  src: local("Roboto");
  size-adjust: 55.5193474%:
  ascent-override: 180.1173909%;
  descent-override: 63.04108683%;
  line-gap-override: 18.01173909%;
}

要求提供意見

如果您對於使用字型指標覆寫功能和「size-adjust」的體驗有任何意見,請與我們聯絡。