針對網站體驗核心指標最佳化調整網頁字型。
本文將說明字型效能最佳做法。網頁字型影響效能的方式有很多種:
- 延遲文字轉譯:如果網路字型尚未載入,瀏覽器通常會延遲文字轉譯。在許多情況下,此動作會延遲 First Contentful Paint (FCP)。在某些情況下,這會延遲最大內容繪製 (LCP)。
- 版面配置位移:字型切換的做法可能會造成版面配置位移,並影響累計版面配置位移 (CLS)。當網頁字型及其備用字型在頁面上占用的空間不同,就會發生這種版面配置變動。
本文件分為三個部分:字型載入、字型提交和字型算繪。每個章節都會說明字型生命週期中該特定部分的運作方式,並提供相應的最佳做法。
正在載入字型
字型是重要的資源,否則,使用者可能無法查看網頁內容。因此,字型載入的最佳做法通常著重於確保字型盡可能提早載入。由於需要分別設定連線,才能下載這些字型檔案,因此必須特別留意從第三方網站載入的字型。
如果不確定網頁的字型是否已按時要求,請在 Chrome 開發人員工具的「Network」面板中查看「Timing」分頁,進一步瞭解情況。
瞭解 @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 字體。
<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 是最新的瀏覽器支援,並且提供最佳壓縮效果。由於使用 Brotli,WOFF2 的壓縮率比 WOFF 高出 30%,因此可減少下載的資料量,進而提升效能。
考量到瀏覽器支援情形,專家現在建議只使用 WOFF2:
事實上,我們也認為是時候宣稱也是很重要的一點:只使用 WOFF2,則不用理會其他東西。
Bram Stein,來自 2022 Web Almanac
這樣一來,CSS 和工作流程會大幅簡化,而且不會意外下載重複或錯誤的字型。所有國家/地區現可支援 WOFF2。因此,除非您需要支援非常古老的瀏覽器,否則請直接使用 WOFF2。如果無法做到,建議您完全不要向這些舊版瀏覽器提供任何網頁字型。如果您已有完善的備用策略,也就沒有問題。使用舊版瀏覽器的訪客會看到備用字型。
子集合字型
字型檔案通常會包含大量字形,用於支援的各種字元。不過,您可能不需要網頁上的所有字元,因此可以透過字型子集來縮減字型檔案的大小。
@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
參數支援此功能),或手動編輯字型檔案,然後自行代管。產生字型子集的工具包括 subfont 和 glyphanger。
請務必檢查字型授權,確認是否允許子集和自架站。
減少使用網路字型
最快可傳送的字型,就是一開始未要求的字型。系統字型和可變字型是兩種可能減少網站上所用網頁字型的做法。
「系統字型」是使用者裝置的使用者介面所使用的預設字型。系統字型通常會因作業系統和版本而異。由於字型已安裝,因此不需要下載字型。系統字型特別適合用於本文。
如要在 CSS 中使用系統字型,請將 system-ui
列為字型系列:
font-family: system-ui
可變字型的概念是,單一可變字型可用來取代多個字型檔案。變數字型會定義「預設」字型樣式,並提供「軸」來操控字型。舉例來說,包含 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 毫秒 | 無 |
- 封鎖期間:瀏覽器要求網路字型時,就會開始封鎖期間。在區塊期間,無法使用網路字型時,字型會以「隱藏」的備用字型呈現,因此使用者不會看到文字。如果在封鎖期間結束時無法使用字型,系統會以備用字型轉譯字型。
- 切換週期:交換週期晚於區塊期間。如果網路字型在換用期間可供使用,就會「換入」。
font-display
策略反映了效能與美感之間的取捨。因此,我們很難建議採取這種做法,因為這取決於個人偏好、網頁字型對網頁和品牌的重要性,以及延遲的字型在操作時放大的可能性。
就大多數網站而言,根據您的最高優先順序,以下是三種最合適的策略:
效能:使用
font-display: optional
。這是最「高效」的做法:文字算繪延遲時間不超過 100 毫秒,且保證不會有與字型交換相關的版面配置變更。不過缺點是延遲抵達時不會使用網路字型。快速顯示文字並繼續使用網路字型:請使用
font-display: swap
,但請務必提早提供字型,以免造成版面配置變更。這個選項的缺點是字型落後時的閃爍轉換。文字以網頁字型顯示:請使用
font-display: block
,但請務必提早提供字型,以便盡可能減少文字的延遲時間。初始文字顯示會延遲。儘管有這個延遲,但由於文字實際上會繪製為不可見,因此仍可能導致版面配置移位,因此會使用備用字型空間來保留空間。載入網路字型後,可能需要不同的空間,因此會產生位移。這可能比font-display: swap
更不明顯,因為文字本身不會顯示為變動。
請注意,這兩種做法可以合併使用:例如,使用 font-display: swap
做為品牌和其他視覺上獨特的網頁元素。內文使用的字型請使用 font-display: optional
。
圖示字型
font-display
策略適用於傳統網頁字型,但不適用於圖示字型。圖示字型的備用字型通常與圖示字型有顯著差異,且其字元的含義也可能完全不同。因此,圖示字型更有可能造成版面配置大幅變動。
此外,使用備用字型可能不實用。盡可能使用 SVG 取代圖示字型,這對無障礙體驗也更為有利。一般來說,熱門圖示字型的新版本會支援 SVG。如要進一步瞭解如何改用可擴充向量圖形,請參閱「Font Awesome」和「Material Design 圖示」。
縮小備用字型和網頁字型之間的間隔
如要降低 CLS 影響,您可以使用 size-adjust
屬性。
結論
雖然網路字型仍是效能瓶頸,但我們提供越來越多選項,讓我們能夠盡可能最佳化,以減少這個瓶頸。