【前端性能優化指南】5.4 - 字體的優化

字體

🔝 頁面靜態資源 | 🔙 上一站 - 圖片css

有些時候,內置的字體並不能知足咱們的需求,若是咱們但願使用一些更有設計性的字體,咱們通常會使用 @font-face 來加載字體文件:前端

@font-face {
    font-family: 'Samplefont';
    src: url(/static/samplefont.woff2) format('woff2'),
         url(/static/samplefont.woff) format('woff');
}
複製代碼

然而這種方式的一大問題在於,在字體加載的期間,瀏覽器頁面是默認不展現文本內容的。即咱們常說的 FOIT (Flash of Invisible Text)。在現代瀏覽器中,FOIT 持續至多 3 秒,會帶來糟糕的用戶體驗。因此在字體這部分的性能優化中,主要關注點在於如何平滑的加載字體。下面有一些解決方案。git

1. 字體裁剪

關於字體的性能問題,不少時候來源於字體文件太大,加載耗時較長。所以,一種處理該問題的方式就是進行字體裁剪,從而爲要加載的字體文件進行「瘦身」。因爲一個字體庫中可能會包含不少字(尤爲是在中文的場景下),可是並不是每一個字都會使用到,所以能夠將不須要使用到的字體剔除。github

例如,對於只須要使用數字的場景,就能夠將其餘無用的字都剔除,只留下數字和一些必要的標點。關於字體裁剪的工具,網上有不少,你們能夠自行選擇。web

2. font-display

你能夠在 @font-face 中設置 font-display: swap,他可讓 FOIT 的默認行爲變爲 FOUT (Flash of Unstyled Text),即先會使用默認字體樣式展現文本,字體加載完畢後再將文本的字體樣式進行替換。瀏覽器

@font-face {
    font-family: 'Samplefont';
    src: url(/static/samplefont.woff2) format('woff2'),
         url(/static/samplefont.woff) format('woff');
    font-display: swap;
}
複製代碼

font-display 的取值包括 auto|block|swap|fallback|optional,這裏詳細介紹了各類值的使用場景[1]。目前(2021.6.5)該屬性的兼容性應該也勉強夠用緩存

3. 內聯字體

咱們在上一節介紹過,可使用 base64 將圖片「內聯」到頁面中。一樣的,字體也可使用這種方式,這樣就避免異步加載字體時的 FOIT 或 FOUT。咱們能夠將字體文件轉爲 base64 的字符串,設置到 @font-face 裏的 src 屬性上:性能優化

@font-face {
    font-family: 'Samplefont';
    src: url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAHyoABMAAAAA4XQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABG…') format('woff2');
}
複製代碼

但這種方式的侷限性在於,在一個 @font-face 中只能加載加載一種字體類型。同時,與使用內聯圖片同樣,這也會將本能夠並行請求的數據量變爲串行。markdown

4. 使用 CSS Font Loading API

CSS Font Loading API 是瀏覽器提供的,能夠用來自定義控制字體加載的 API。這樣你就能夠在 JavaScript 中進行字體的加載,等加載完成後,再將須要應用新字體的元素設置爲對應的樣式,例如添加一個對應的 className。這裏介紹了如何使用 CSS Font Loading API[2]app

不過目前(2021.6.5) CSS Font Loading API 也可能又兼容性問題。同時,因爲一些困難也沒法實現一個完美的 polyfill。所以若是想要使用相似的能力,能夠考慮 Font Face Observer這個庫。基本的使用方式以下:

const font = new FontFaceObserver('Samplefont');

font.load(null, 5000).then(
    () => document.documentElement.classList.add('loaded'),
    () => console.log('Font is not available')
);
複製代碼
@font-face {
    font-family: 'Samplefont';
    src: url(/static/samplefont.woff2) format('woff2'),
         url(/static/samplefont.woff) format('woff');
}

body {
    font-family: sans-serif;
}

.loaded h1 {
    font-family: Samplefont, sans-serif;
    font-weight: 700;
}
複製代碼

5. FOFT

在須要加載同一字體的粗體、斜體時,FOFT (Flash of Faux Text) 方法會很是有效。

首先你須要瞭解的是,對於一種字體,它的斜體與粗體是有專門的字符集的;與此同時,若是你指定了某種字體的粗體,但瀏覽器沒有加載,那麼你可使用 font-synthesis 屬性來讓瀏覽器幫你模擬。而當實際的粗體或斜體加載完畢後,再使用實際的字體集。

具體實踐起會藉助上面提到的 CSS Font Loading API 或者 Font Face Observer,實現當字體加載完畢後的樣式修改。


瞭解完字體的優化措施你會發現,它們主要集中於 如何經過加載策略來下降甚至消除 FOIT。固然上面提到的這些策略與技術你能夠組合使用,以達到所需的優化效果。

若是還想了解更多關於字體加載的問題,能夠看看這篇文章裏總結的各種加載策略[3],它還隨文提供了相應的代碼示例。

image.png

關於字體的性能優化就到這了,下面咱們會進入到頁面靜態資源優化的最後一站 —— 視頻。

喜歡的朋友歡迎關注個人博客RSS 訂閱


「性能優化」系列內容

  1. 帶你全面掌握前端性能優化 🚀
  2. 如何利用緩存減小遠程請求?
  3. 如何加快請求速度?
  4. 如何加速頁面解析與處理?
  5. 靜態資源優化的整體思路是什麼?
    1. 如何針對 JavaScript 進行性能優化?
    2. 如何針對 CSS 進行性能優化?
    3. 圖片雖好,但也會帶來性能問題
    4. 字體也須要性能優化麼?(本文)
    5. 🔜 如何針對視頻進行性能優化?
  6. 如何避免運行時的性能問題?
  7. 如何經過預加載來提高性能?
  8. 尾聲

目前內容已所有更新至 ✨ fe-performance-journey ✨ 倉庫中,陸續會將內容同步到掘金上。若是但願儘快閱讀相關內容,也能夠直接去該倉庫中瀏覽。


參考資料

  1. Controlling Font Performance with font-display
  2. Getting started with CSS Font Loading
  3. A COMPREHENSIVE GUIDE TO FONT LOADING STRATEGIES
相關文章
相關標籤/搜索