縮小網頁字型大小

字體是良好設計、品牌宣傳、可讀性和無障礙設計的基礎。網頁字型可實現上述所有功能,還能選取、搜尋、縮放文字,並支援高 DPI,無論螢幕大小和解析度為何,都能提供一致且清晰的文字轉譯效果。WebFont 對於良好的設計、使用者體驗和效能至關重要。

網頁字型最佳化是整體成效策略的關鍵部分。每種字型都是額外資源,部分字型可能會阻礙文字的算繪作業,但網頁使用 WebFonts 不代表算繪速度一定會變慢。相反地,經過最佳化的字型搭配適當的策略,在網頁上載入及套用,有助於縮減網頁總大小,並縮短網頁算繪時間。

網站字型剖析

網頁字型是一組字形,每個字形都是描述字母或符號的向量形狀。因此,特定字型檔案的大小取決於兩個簡單的變數:每個字形的向量路徑複雜度,以及特定字型中的字形數量。舉例來說,Open Sans 是最熱門的 WebFont 之一,內含 897 個字形,包括拉丁文、希臘文和西里爾文字元。

字型字符表

挑選字型時,請務必考慮支援的字元集。如果需要將網頁內容翻譯成多種語言,請使用可為使用者提供一致外觀和體驗的字型。舉例來說,Google 的 Noto 字型系列旨在支援全球所有語言。不過請注意,如果下載包含所有語言的 Noto,ZIP 壓縮檔大小會超過 1.1 GB。

本文將說明如何縮減網頁字型的傳送檔案大小。

網頁字型格式

目前網路上有兩種建議使用的字型容器格式:

WOFFWOFF 2.0 獲得廣泛支援,所有新式瀏覽器都支援這兩種格式。

  • 向新式瀏覽器提供 WOFF 2.0 變體。
  • 如果絕對必要 (例如仍需支援 Internet Explorer 11),請將 WOFF 做為備援。
  • 或者,您也可以考慮不要為舊版瀏覽器使用網頁字型,改用系統字型。這項做法也可能提升舊型裝置的效能。
  • 由於 WOFF 和 WOFF 2.0 涵蓋所有新舊瀏覽器,因此不再需要使用 EOT 和 TTF,否則可能會導致網頁字型下載時間變長。

網頁字型和壓縮

WOFF 和 WOFF 2.0 都內建壓縮功能。WOFF 2.0 的內部壓縮功能使用 Brotli,壓縮效果比 WOFF 更好,最多可提升 30%。詳情請參閱 WOFF 2.0 評估報告

最後,值得注意的是,部分字型格式含有額外的中繼資料,例如字型提示字距資訊,這些資訊在某些平台上可能並非必要,因此可進一步最佳化檔案大小。舉例來說,Google Fonts會為每個字型維護 30 多個最佳化變體,並自動偵測及提供各平台和瀏覽器的最佳變體。

使用 @font-face 定義字型系列

@font-face CSS at 規則可讓您定義特定字型資源的位置、樣式特徵,以及應使用的 Unicode 碼位。這類 @font-face 宣告的組合可用於建構「字型系列」,瀏覽器會使用該系列評估需要下載哪些字型資源,並套用至目前網頁。

考慮使用變數字型

如果您需要多種字型變體,變數字型可大幅縮減字型檔案大小。您不必載入一般和粗體樣式及其斜體版本,只要載入包含所有資訊的單一檔案即可。不過,可變字型檔案大小會大於個別字型變體,但小於多種變體的組合。與其提供一個大型可變字型,不如先提供重要字型變體,其他變體則稍後再下載。

所有新式瀏覽器現在都支援可變字型,詳情請參閱「網頁可變字型簡介」。

選取合適的格式

每個 @font-face 宣告都會提供字型系列名稱,做為多個宣告的邏輯群組、字型屬性 (例如樣式、粗細和延展) 和 src 描述元,後者會指定字型資源位置的優先順序清單。

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome.woff2') format('woff2'),
       /* Only serve WOFF if necessary. Otherwise,
          WOFF 2.0 is fine by itself. */
       url('/fonts/awesome.woff') format('woff');
}

@font-face {
  font-family: 'Awesome Font';
  font-style: italic;
  font-weight: 400;
  src: local('Awesome Font Italic'),
       url('/fonts/awesome-i.woff2') format('woff2'),
       url('/fonts/awesome-i.woff') format('woff');
}

首先,請注意上述範例定義了單一的「Awesome Font」系列,其中包含兩種樣式 (一般和斜體),每種樣式都指向一組不同的字型資源。反過來說,每個 src 描述元都包含以半形逗號分隔的資源變體清單,並依優先順序排列:

  • local() 指令可讓您參照、載入及使用本機安裝的字型。如果使用者已在系統上安裝字型,則完全不會用到網路,速度最快。
  • url() 指令可載入外部字型,並可選擇性地包含 format() 提示,指出所提供網址參照的字型格式。

瀏覽器判斷需要字型時,會依指定順序逐一檢查提供的資源清單,並嘗試載入適當的資源。舉例來說,按照上述範例:

  1. 瀏覽器會執行網頁版面配置,並判斷轉譯網頁上指定文字所需的字型變體。如果字型不屬於網頁的 CSS 物件模型 (CSSOM),瀏覽器就不會下載,因為不需要這些字型。
  2. 瀏覽器會檢查本機是否提供每種必要字型。
  3. 如果本機沒有該字型,瀏覽器會疊代外部定義:
    • 如果存在格式提示,瀏覽器會在啟動下載前檢查是否支援該提示。如果瀏覽器不支援提示,就會前往下一個提示。
    • 如果沒有格式提示,瀏覽器會下載資源。

結合本機和外部指令,並提供適當的格式提示,即可指定所有可用的字型格式,其餘部分則交由瀏覽器處理。瀏覽器會判斷需要哪些資源,並選取最佳格式。

Unicode 範圍子集

除了樣式、粗細和延展等字型屬性外,@font-face 規則還可讓您定義每個資源支援的一組 Unicode 碼位。這項功能可讓您將大型 Unicode 字型拆分成較小的子集 (例如拉丁文、西里爾文和希臘文子集),並只下載在特定網頁上算繪文字所需的字形。

unicode-range 描述元可讓您指定以半形逗號分隔的範圍值清單,每個值可採用下列三種不同形式:

  • 單一碼點 (例如 U+416)
  • 間隔範圍 (例如 U+400-4ff):表示範圍的開始和結束碼位
  • 萬用字元範圍 (例如 U+4??):? 字元表示任何十六進位數字

舉例來說,您可以將「Awesome Font」字型系列拆分成拉丁文和日文子集,瀏覽器會視需要下載每個子集:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-jp.woff2') format('woff2');
  /* Japanese glyphs */
  unicode-range: U+3000-9FFF, U+ff??;
}

使用 Unicode 範圍子集,並為字型的每個樣式變體提供個別檔案,即可定義複合字型系列,下載速度更快,效率也更高。訪客只會下載需要的變體和子集,不會被迫下載可能永遠不會在網頁上看到或使用的子集。

幾乎所有瀏覽器都支援unicode-range。如要與舊版瀏覽器相容,您可能需要改用「手動子集」。在這種情況下,您必須改為提供單一字型資源,其中包含所有必要子集,並向瀏覽器隱藏其餘部分。舉例來說,如果網頁只使用拉丁字元,您可以移除其他字形,並將該特定子集做為獨立資源提供。

  1. 決定需要哪些子集:
    • 如果瀏覽器支援 unicode-range 子集,系統會自動選取正確的子集。網頁只需要提供子集檔案,並在 @font-face 規則中指定適當的 unicode 範圍。
    • 如果瀏覽器不支援 unicode-range 子集,網頁就必須隱藏所有不必要的子集,也就是開發人員必須指定必要的子集。
  2. 產生字型子集:
    • 使用開放原始碼的 pyftsubset 工具,建立字型子集並進行最佳化。
    • 部分字型伺服器 (例如 Google 字型) 預設會自動建立子集。
    • 部分字型服務允許透過自訂查詢參數手動建立子集,您可以使用這項功能,為網頁手動指定所需子集。請參閱字型提供者的說明文件。

字型選取與合成

每個字型系列可能由多種樣式變體 (一般、粗體、斜體) 組成,且每種樣式都有多種粗細。而每個字型又可能包含非常不同的字符形狀,例如不同的間距、大小或完全不同的形狀。

字型粗細

上圖說明字型系列提供三種不同的粗體權重:

  • 400 (一般)。
  • 700 (粗體)。
  • 900 (特粗)。

其他介於中間的變體 (以灰色表示) 會由瀏覽器自動對應至最接近的變體。

如果指定的權重沒有對應的字面,系統會使用權重相近的字面。一般來說,粗體權重會對應到較重的字體,而細體權重則會對應到較輕的字體。

CSS 字型比對演算法

類似的邏輯也適用於斜體變體。字型設計師會控管要製作哪些變體,而您則可控管要在網頁上使用哪些變體。由於每個變體都是獨立下載項目,因此建議盡量減少變體數量。舉例來說,您可以為「Awesome Font」系列定義兩種粗體變體:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 700;
  src: local('Awesome Font'),
       url('/fonts/awesome-l-700.woff2') format('woff2');
  /* Latin glyphs */
  unicode-range: U+000-5FF;
}

上述範例宣告了「Awesome Font」系列,該系列由兩個資源組成,涵蓋同一組拉丁字元 (U+000-5FF),但提供兩種不同的「權重」:一般 (400) 和粗體 (700)。不過,如果其中一項 CSS 規則指定不同的字體粗細,或將 font-style 屬性設為 italic,會發生什麼情況?

  • 如果找不到完全相符的字型,瀏覽器會改用最接近的字型。
  • 如果找不到相符的樣式 (例如上述範例中未宣告斜體變體),瀏覽器就會自行合成字型變體。
字型合成

上例顯示 Open Sans 的實際字型結果與合成字型結果之間的差異。所有合成變體都是從單一 400 權重的字型產生。如您所見,結果有明顯差異。如何產生粗體和斜體變體並未指定。因此,結果會因瀏覽器而異,且高度取決於字型。

網頁字型大小最佳化檢查清單

  • 稽核及監控字型使用情形:請勿在網頁上使用過多字型,並盡量減少每種字型的變體數量。這有助於為使用者提供更一致且更快速的體驗。
  • 盡量避免使用舊版格式:EOT、TTF 和 WOFF 格式比 WOFF 2.0 大,EOT 和 TTF 是完全不必要的格式,但如果您需要支援 Internet Explorer 11,或許可以接受 WOFF。如果您只指定現代瀏覽器,只使用 WOFF 2.0 是最簡單且效能最佳的選項。
  • 建立字型資源子集:許多字型都可以建立子集,或分割成多個 Unicode 範圍,只提供特定網頁所需的字元。這可縮減檔案大小,並提升資源的下載速度。不過,定義子集時,請務必盡量重複使用字型。舉例來說,請勿在每個頁面下載不同但重疊的字元集。建議根據文字系統建立子集,例如拉丁文和西里爾文。
  • src 清單中優先使用 local()src 清單中將 local('Font Name') 列為第一項,可確保系統不會為已安裝的字型發出 HTTP 要求。
  • 使用 Lighthouse 測試文字壓縮

對最大內容繪製 (LCP) 和累計版面配置位移 (CLS) 的影響

視網頁內容而定,文字節點可視為 Largest Contentful Paint (LCP) 的候選項目。因此,請務必按照本文建議,盡量縮小網頁字型,讓使用者盡快看到網頁上的文字

如果您擔心網頁字型資源過大,導致網頁文字顯示時間過長,font-display 屬性提供多項設定,有助於在字型下載期間避免文字隱形。不過,使用 swap 值可能會導致版面配置大幅位移,進而影響網站的累計版面配置位移 (CLS)。建議盡可能使用 optionalfallback 值。

如果網頁字型對品牌宣傳 (以及使用者體驗) 至關重要,請考慮預先載入字型,讓瀏覽器能搶先要求字型。如果您使用 font-display: swap,這項設定可縮短交換期;如果您未使用 font-display,則可縮短封鎖期。