字型的最佳做法

針對 Core Web Vitals 進行網站字型最佳化。

Katie Hempenius
Katie Hempenius

本文將討論字型的效能最佳做法。網頁字型對效能的影響有很多種:

本文分為三個部分:字型載入字型傳送字型顯示。每一節都會說明字型生命週期中特定層面的運作方式,並提供對應的最佳做法。

正在載入字型

字型通常是重要資源,因為如果沒有字型,使用者可能無法查看網頁內容。因此,字型載入的最佳做法通常著重於確保盡快載入字型。此外,也須特別留意從第三方網站載入的字型,因為這些字型檔案需要另外設定連線。

如果您不確定是否要及時要求網頁的字型,請前往 Chrome 開發人員工具的「網路」面板查看「時間」分頁。

開發人員工具中的「時間」分頁螢幕截圖

瞭解 @font-face

在探討載入字型的最佳做法之前,請務必先瞭解 @font-face 的運作方式,以及這對於字型載入作業有何影響。

使用任何網路字型時,@font-face 宣告是不可或缺的一環。它至少會宣告用於參照字型的名稱,並且指出對應字型檔案的位置。

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

常見的誤解是,系統在遇到 @font-face 宣告時要求字型,但這並不正確。@font-face 宣告本身不會觸發字型下載作業。相反地,只有在網頁使用的樣式參照某個字型時,系統才會下載該字型。如下所示:

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}

h1 {
  font-family: "Open Sans"
}

換句話說,在上述範例中,只有在網頁含有 <h1> 元素時,系統才會下載 Open Sans

因此,在考慮如何最佳化字型時,您務必在樣式表中考慮字型和使用字型檔案的方式一樣重要。變更樣式表的內容或交付方式,會對字型送達時產生重大影響。同樣地,移除未使用的 CSS 和分割樣式表,可減少網頁載入的字型數量。

內嵌字型宣告

多數網站都會受益於主要文件的 <head> 中內嵌字型宣告及其他重要樣式,而不是將字型宣告加入外部樣式表。這可讓瀏覽器更快找到字型宣告,因為瀏覽器不需要等待外部樣式表下載。

<head>
  <style>
    @font-face {
        font-family: "Open Sans";
        src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    }

    body {
        font-family: "Open Sans";
    }

    ...etc.

  </style>
</head>
敬上

由於並非所有網站都能達成,內嵌重要的 CSS 是較先進的技術。雖然這麼做有明顯提升成效的好處,但還需要額外的程序和建構工具,才能確保必要的 CSS (最好是重要的 CSS) 內嵌正確,而且其他任何 CSS 都能以非轉譯的封鎖方式傳送。

預先連線至重要的第三方來源

如果你的網站會載入第三方網站的字型,我們強烈建議使用 preconnect 資源提示,提早與第三方來源建立連線。資源提示應置於文件的 <head> 中。下方的資源提示會設定載入字型樣式表的連線。

<head>
  <link rel="preconnect" href="https://fonts.com">
</head>

如要預先連接用於下載字型檔案的連線,請新增使用 crossorigin 屬性的獨立 preconnect 資源提示。有別於樣式表,字型檔案必須透過 CORS 連線傳送。

<head>
  <link rel="preconnect" href="https://fonts.com">
  <link rel="preconnect" href="https://fonts.com" crossorigin>
</head>

使用 preconnect 資源提示時,請注意字型提供者可能會從不同來源提供樣式表和字型。例如,以下是 preconnect 資源提示將用於 Google Fonts 的方式。

<head>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
</head>
敬上

使用 preload 載入字型時需小心

雖然在網頁載入程序初期,preload 能夠有效偵測字型,但卻浪費瀏覽器資源載入其他資源所費不貲。

內嵌字型宣告和調整樣式表可能會更有效。比起提供解決方法,這些調整會更接近處理遲緩字型的根本原因。

此外,使用 preload 做為載入字型的策略時也應謹慎使用,因為它能繞過部分瀏覽器內建的內容交涉策略。舉例來說,preload 會忽略 unicode-range 宣告,如果審慎使用,則應只用於載入單一字型格式。

不過,使用外部樣式表時,預先載入最重要的字型非常有效率,因為瀏覽器必須等到之後才會發現是否需要該字型。

字型傳送

字型顯示速度越快,文字算繪速度就越快。此外,如果能提早提供字型,這也有助於減少因字型替換造成的版面配置位移。

使用自行代管的字型

紙上來說,使用自行代管的字型會省去第三方連線設定,因此效能較佳。但實際上,這兩種選項的成效差異較不明確。舉例來說,Web Almanac 發現使用第三方字型的網站,轉譯速度比使用第一方字型的字型更快。

如果您考慮使用自行代管的字型,請確認網站使用內容傳遞網路 (CDN)HTTP/2。若不使用這些技術,自行代管的字型就難以提高成效。詳情請參閱內容傳遞網路

如果您使用自行代管的字型,建議您一併套用第三方字型供應商通常自動提供的字型檔案最佳化功能,例如字型子設定和 WOFF2 壓縮。至於需投入多少心力,則取決於網站支援的語言。請特別注意,針對 CJK 語言最佳化字型並不容易。

使用 WOFF2

就現代字型字型而言,WOFF2 是最新的瀏覽器支援,並且提供最佳壓縮效果。由於 WOFF2 採用 Brotli 技術,因此將壓縮結果比 WOFF 多了 30%,可減少下載的資料量,進而提升執行效能。

基於瀏覽器支援,專家現在建議只使用 WOFF2:

事實上,我們也認為是時候宣稱也是很重要的一點:只使用 WOFF2,則無須處理所有其他事務。

這樣可以大幅簡化 CSS 和工作流程,避免意外下載重複或不正確的字型。所有國家/地區現可支援 WOFF2。因此,除非需要支援非常古老的瀏覽器,否則只要使用 WOFF2 即可。如果無法,建議您也不要為舊版瀏覽器提供任何網路字型。如果您已製定完善的備用策略,也就不會發生問題。使用舊版瀏覽器的訪客只會看到備用字型。

Bram Stein,2022 Web Almanac 報導

子集合字型

一般來說,字型檔案含有大量支援各種字元的字符。不過,您可能不需要網頁中的所有字元,只要利用子設定字型,就能縮減字型檔案的大小。

@font-face 宣告中的 unicode-range 描述元會告知瀏覽器可以使用字型的哪些字元。

@font-face {
    font-family: "Open Sans";
    src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
    unicode-range: U+0025-00FF;
}

如果網頁包含一或多個與 Unicode 範圍相符的字元,系統會下載字型檔案。unicode-range 通常用於根據網頁內容所使用的語言,提供不同的字型檔案。

unicode-range 通常與子設定技術搭配使用。部分字型包含原始字型檔案中的一小部分字符。例如,網站可能會產生拉丁文和斯拉夫文字元的子集,而不是向所有使用者提供所有字元。每個字型的字符數量有很大的差異:拉丁字型通常大小約介於每種字型 100 至 1000 字符上;CJK 字型可超過 10,000 個字元。移除未使用的字符可大幅縮減字型的檔案大小。

部分字型供應程式可能會自動提供有不同子集的字型檔案。舉例來說,Google Fonts 預設會執行這項操作:

/* devanagari */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJbecnFHGPezSQ.woff2) format('woff2');
  unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
}
/* latin-ext */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJnecnFHGPezSQ.woff2) format('woff2');
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

改用自行託管時,這項最佳化功能很容易遭到偵測,且會在本機產生較大的字型檔案。

此外,在字型提供者允許的情況下,您也可以透過 API (Google Fonts 提供 text 參數來支援這項操作),或者手動編輯字型檔案,然後自行進行代管。可產生字型子集的工具包括 subfontglyphanger。不過,請檢查您使用的字型授權是否允許子設定和自行代管。

減少使用網路字型

最快顯示的字型是一開始沒有要求的字型。系統字型和可變字型提供兩種可能,可減少網站所用網頁字型數量的方法。

系統字型是使用者裝置的使用者介面所使用的預設字型。系統字型通常會因作業系統和版本而異。該字型已安裝,因此不需下載該字型。系統字型特別適合用於內文。

如要在 CSS 中使用系統字型,請將 system-ui 列為字型系列:

font-family: system-ui

可變字型的概念是單一可變字型可以用來取代多個字型檔案。變數字型在定義「default」的字型樣式並提供「axes」來操控字型。舉例來說,使用 Weight 軸的變數字型可用於實作過去需要分別針對淺色、一般、粗體和額外粗體顯示字型的字母。

改用可變字型,不是每個人都有好處。可變字型包含許多樣式,因此檔案大小通常比只包含一種樣式的個別非變數字型更大。對使用可變字型來說,使用可變字型有最大改善效果的網站,就是使用 (有需要) 各種字型樣式和粗細的網站。

字型顯示

瀏覽器面對尚未載入的網頁字型時,會面臨困境。在網頁字型顯示之前,瀏覽器是否應暫停顯示文字?還是在網頁字型送達之前,將文字以備用字型顯示?

不同瀏覽器處理這種情況的方式不同。根據預設,如果未載入關聯的網路字型,以 Chromium 和 Firefox 的瀏覽器最多會封鎖文字轉譯最多 3 秒。Safari 會無限期禁止轉譯文字。

您可以使用 font-display 屬性來設定此行為。這個選項可能會造成重大影響:font-display 可能會影響 LCP、FCP 和版面配置穩定性。

選擇合適的「font-display」策略

font-display 會通知瀏覽器在未載入相關網路字型時,應如何繼續轉譯文字。是根據字型定義。

@font-face {
  font-family: Roboto, Sans-Serif
  src: url(/fonts/roboto.woff) format('woff'),
  font-display: swap;
}

font-display 有五個可能的值:

封鎖期間 切換週期
自動 因瀏覽器而異 因瀏覽器而異
封鎖 2 到 3 秒 無限
交換 0 毫秒 無限
備用 100 毫秒 3 秒
選用 100 毫秒
  • 封鎖期間:封鎖期是從瀏覽器要求網路字型時開始。在區塊期間,如果沒有網路字型,則會以隱形的備用字型顯示,因此使用者不會看到文字。如果所選字型在封鎖期間結束後無法使用,系統就會以備用字型顯示該字型。
  • 切換週期:交換週期晚於區塊期間。如果可在替換期間使用網路字型,字型會顯示為「swapped」。

font-display 策略反映了不同觀點,說明成效與美學之間的取捨。要提供建議的做法並不容易,因為做法的確取決於個人偏好、網頁字型對於網頁和品牌的重要性,以及退信的字型在切換後會如何變形。

對大多數網站來說,以下是最合適的三種策略:

  • 如果效能是首要考量:請使用 font-display: optional。這是最「效能」方法:文字顯示時間不得超過 100 毫秒,而且我們確保不會發生字型切換的相關版面配置位移。然而,這個缺點是延遲抵達時不會使用網路字型。

  • 如果快速顯示文字是優先考量,但您仍想確保使用網路字型:請使用 font-display: swap,但務必盡早提供字型,以免造成版面配置位移。這個選項的缺點是字型延遲到來時,會逐漸移位。

  • 如果要確保文字顯示網頁字型是首要考量:請使用 font-display: block,但也要盡早提供字型,以縮短文字延遲時間。這個缺點是初始文字顯示會延遲。請注意,即使發生此情況,這仍可能會在文字實際繪製時造成版面配置位移,而導致備用字型空間成為保留空間。網路字型載入後,可能需要多餘的空間並因此轉換。不過,這可能會比 font-display: swap 更簡潔的移位,因為文字本身不會改變。

,瞭解如何調查及移除這項存取權。

另請注意,這兩種方法可以同時採用:例如,使用 font-display: swap 來宣傳品牌和其他外觀獨具的網頁元素。使用 font-display: optional 做為內文中使用的字型。

縮小備用字型和網頁字型之間的間隔

如要減少 CLS 的影響,您可以使用新的 size-adjust 屬性。詳情請參閱 CSS 相關文章size-adjust。這項新工具是工具集的新增功能,因此目前較為進階,且需要額外手動操作。但日後不妨多方嘗試,觀察日後可用的工具改良方法!

結論

網頁字型仍是一個效能瓶頸,但我們提供多種選項,讓我們能夠最佳化字型,盡可能減少這個瓶頸。