最近在做專案最佳化的時候偶然發現,我們做的頁面第一次進入字型會有一個閃爍的情況,這是什麼原因呢?下面來和大家仔細說說,先看效果
閃爍問題原因?
其實這裏背後的原因 很簡單就是,我們沒有提前載入字型包,導致進入頁面使用到了字型然後進行網路請求,但由於網路請求需要一段時間向服務端獲取資源,這段時間前端頁面會使用預設字型,此時從預設字型轉化為請求的字型就出現閃爍。
使用 css傳送網路請求載入字型
@font-face{ font-family: 'JD-UDC-Bold'; font-display: swap; src: url('./JD-UDC-Bold.otf') }
以上程式碼應該比較容易理解,font-family
和 src
就不和大家講解了。
font-display 可選引數
``` /* 關鍵字值 */ font-display: auto; font-display: block; font-display: swap; font-display: fallback; font-display: optional; ```
屬性值 | 描述 |
---|---|
auto | 預設值。瀏覽器根據情況決定如何處理字型顯示。 |
block | 在字型載入完成之前,使用佔位符進行顯示,避免文字閃現或導致佈局變化。 |
swap |
在字型載入完成之前,使用與自定義字型相似的系統預設字型進行顯示,保持整體佈局的穩定性。 |
fallback | 在字型載入完成之前,使用與自定義字型相似的系統預設字型進行顯示,並在載入完成後切換為自定義字型。 |
optional | 優先顯示系統預設字型,在自定義字型在載入期間可用時切換為自定義字型。 |
如何解決 ?
在下給大家提供兩種方案
1:使用 JS 預載入 字型包
此方案也是當前生產上正在使用的方式,使用JS提供的內建API FontFace
進行請求
async loadFund () { const fontList = ['JR-UDC-Bold.otf' , 'JR-UDC-Light.otf'] // 定義字型檔名稱 for(const fontResolveUrL of fontList){ // 迴圈字型檔名稱 if(typeof FontFace !== 'undefined'){ // 適配低版本 不支援 FontFace 的情況 const fontInstance = new FontFace(fontResolveUrL.replace(/.otf/ , '') , `url(../fonts/${fontResolveUrL})`) // 如果瀏覽器支援 FontFace 則建立例項 await fontInstance.load() // 開始載入字型 }else{ // 不相容 可以手動傳送一個 get請求 請求伺服器資源 } } } setTimeout(loadFund , 500)// 使用 非同步載入不要影響頁面的FCP
以上程式碼 主要的邏輯時 以下幾點
定義非同步函式
迴圈載入字型
判斷瀏覽器是否支援FontFace ,不支援可以走 else 手動獲取 伺服器資源
當你使用 FontFace 物件載入的時候 , 其實內部 幫你傳送網路請求,獲取伺服器資源。
FontFace 的引數
new FontFace('字型名稱' , 字型資源路徑 , 選項描述)
。
2:使用css載入 字型包
@font-face { font-family: 'MyFont'; src: url('path/to/your/font.woff2') format('woff2'), url('path/to/your/font.woff') format('woff'), url('path/to/your/font.ttf') format('truetype'); font-weight: normal; font-style: normal; }
總結
閃爍的問題來源於 字型沒有被載入,當被載入之後 css渲染解析時,可以直接獲取到資源,無需等待網路請求緩衝過程。