縮小網頁字型大小

Ilya Grigorik
Ilya Grigorik
Jeremy Wagner
Jeremy Wagner

字體排版是優質設計、品牌宣傳、可讀性和無障礙設計的基礎。網路字型可提供上述所有功能,甚至更多:文字可供選取、搜尋、縮放,且支援高 DPI,無論螢幕大小和解析度為何,都能提供一致且清晰的文字顯示效果。Web Fonts 對良好的設計、使用者體驗和效能至關重要。

網頁字型最佳化是整體成效策略的重要一環。每個字型都是額外資源,有些字型可能會阻擋文字的算繪,但網頁使用 Web 字型並不代表算繪速度一定會變慢。相反地,如果您使用經過最佳化的字型,並採用明智的策略來載入及套用字型,就能縮減網頁總大小,並縮短網頁轉譯時間。

網路字型的結構

網頁字型是一組字符,每個字符都是描述字母或符號的向量圖形。因此,兩個簡單的變數會決定特定字型檔案的大小:每個字元圖形的向量路徑複雜度,以及特定字型中的字元圖形數量。���例來說,Open Sans 是其中一個最受歡迎的 Web 字型,包含 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 字體會為每個字型維護 30 多個最佳化變化版本,並自動偵測並提供每個平台和瀏覽器的最佳變化版本。

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

@font-face CSS at-rule 可讓您定義特定字型資源的位置、樣式特性,以及應使用的 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 範圍子集,則會自動選取正確的子集。這個頁面只需要提供子集檔案,並在 @font-face 規則中指定適當的萬國碼範圍。
    • 如果瀏覽器不支援 Unicode 範圍子集,則網頁必須隱藏所有不必要的子集,也就是說,開發人員必須指定必要的子集。
  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) 的影響

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

如果您擔心即使已盡力最佳化,網頁文字仍可能因大型網路字型資源而顯示過久,font-display 資源類別提供多項設定,有助於您在字型下載期間避免文字顯示不見。不過,使用 swap 值可能會造成顯著的版面配置位移,進而影響網站的累積版面配置位移 (CLS)。盡可能使用 optionalfallback 值。

如果網頁字型對品牌形象 (以及延伸至使用者體驗) 至關重要,建議您預先載入字型,讓瀏覽器提早要求字型。這麼做可以縮短交換期 (如果您使用 font-display: swap) 或阻斷期 (如果您未使用 font-display)。