引入第三方字體一定要注意字體版權問題
前言
承接上文web 端字體兼容性適配之后,好久沒有總結 CSS3 引入字體 @font-face
相關的文章了。一是在掌握 @font-face
的基本使用要領后沒遇過兼容性問題,二是覺得 @font-face
已經兼容 ie9+及現代瀏覽器了,兼容性問題基本可以忽略不計了。事與願違的是,在多次實戰中發現引入第三方字體會出現許多奇形怪狀的問題,譬如字體文件的編碼問題引發字體可以在桌面系統正常使用而在 Web 端不起作用、字體文件中英文或其他外語的字體行高差異問題、字體文件的等寬比在不同瀏覽器顯示差異問題......現對web 端字體兼容性適配作補充,如果不妥請各位大佬抬手指正(#.#)。
字體兼容性
字體編碼
前段時間有幾個需要引入第三方字體的項目,引入過西文、韓文、泰文、以及種類繁多讓你眼花繚亂的中文字體,可能是因為引入那種中文字體比較多的緣故吧,老覺得中文字體的兼容性可能會多些,其中編碼兼容性像一座大山。
或許你會遇到過這樣的情景,字體在 Photoshop 可以正常使用,放在 Web 端通過 @font-face
引入后字體顯示不起作用。與相似的還有引入字體在 IE、Firefox 等瀏覽器正常使用,在 chrome 瀏覽器卻顯示編碼報錯不起作用如:OTS parsing error: cmap: Failed to serialize table
的情況,或者完全因為字體編碼格式不是被該瀏覽器所支持。
“工欲善其事必先利其器”,解決編碼問題這里推薦兩個字體轉碼工具:
詳情請前往原文-CSS3 使用@font-face 引入字體的兼容性方案及優化
字體優化
字體壓縮
字體文件體積一般少則 2~4M,多則能達到 20~30M 之多,因此 直接 引入第三方字體尚且存在很大缺陷,尤其是在移動端使用。
當然開發者的智慧是無窮的,社區對此類問題也提供了字體壓縮的解決方案。
常用字體壓縮有:
font-spider
fontmin
使用 rel="preload"
優化字體加載
由於自定義字體只有當前頁面被引用到的時候,瀏覽器才會對字體進行加載。為了更快的加載字體文件,可以使用rel="preload"
來達到效果
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin />
FOUT(Flash of Unstyled Text) 優化
FOIT(Flash of Invisible Text)問題:瀏覽器在加載字體的時候的默認表現形式,也就是在字體加載過程中,頁面是看不到文本內容的。在現代瀏覽器中,FOIT 會導致這種現象出現至多 3 秒。FOIT 會導致很差的用戶體驗,這是我們需要盡量去避免的。
FOUT:在字體加載過程中使用默認的系統字體,字體加載完后顯示加載的字體,如果超過了 FOIT(3s)字體還沒加載,則繼續使用默認的系統字體。
FOUT 特性:
- 通過
@font-face
設置 屬性font-display
來實現,默認為 auto。 - IE 瀏覽器和 Edge 不會等待 FOIT 超時才顯示默認字體,會立即顯示默認字體。FOUT 比 FOIT 好,但是需要注意它引起的 reflow。
為了實現 FOUT,一般可設置 font-display
為 swap
、fallback
或 optional
。
swap
:為字體提供一個非常小的阻塞周期和無限的交換周期。(自定義字體加載成功即顯示字體樣式,可以在頁面中看到的一個字體替換的效果)fallback
:為字體提供一個非常小的阻塞周期和短暫的交換周期。(Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a short swap period (3s is recommended in most cases).)optional
:為字體提供一個非常小的阻塞周期,並且沒有交換周期。(Gives the font face an extremely small block period (100ms or less is recommended in most cases) and a 0s swap period)
@font-face {
font-family: 'fcustom';
font-display: 'swap';
font-display: 'fallback';
font-display: 'optional';
}
使用監聽字體加載
FontFaceObserver
通過使用插件 npm i fontfaceobserver
來監聽字體加載完成,從而按需設置字體樣式。
在字體加載前預算一種字體或使用 loading 效果什么的,字體加載成功后切換字體即可
// css 中 @font-face 已定義好
import FontFaceObserver from 'fontfaceobserver';
function loadfont() {
var ffo = new FontFaceObserver('My Family');
ffo.load().then(() => {
document.getElementById('fcustom').style.fontFamily = 'My Family';
});
}
Font Load API
方法效果同 FontFaceObserver。
使用 Font Load API 加載字體,字體在加載完成前預算一種字體,字體加載完成切換相應的 CSS 即可。
但是需注意 Font Load API 是原生的 API,有兼容性問題。
<script>
document.fonts.load('1em open_sansregular').then(function() {
var docEl = document.documentElement;
docEl.className += ' open-sans-loaded';
});
</script>
<style>
.open-sans-loaded h1 {
font-family: open_sansregular;
}
</style>
字體轉 BASE64URI
核心要義就是將@font-face 中定義字體時的路徑直接改為字體的 base64 編碼。
- 優點:因為不會產生 FOIT 和 FOUT。所以不會有 reflow 和 repaint。
- 缺點:
- 字體轉成 base64 也會很大,會影響頁面首次加載速度。
- 不支持逗號分隔的形式加載多種格式的字體,只能加載一種格式字體。這導致你為了盡可能保證所有瀏覽器都可以兼容,通常會指定為 woff 格式,因為 woff 格式兼容性好,但是卻沒法使用更小體積的 woff2 格式,因為 woff2 格式兼容性差點。
異步加載 BASE64 格式 URI 字體
通過異步的方式插入帶有 BASE64 格式 URI 字體的 CSS 鏈接。
更多詳情請前往原文-CSS3 使用@font-face 引入字體的兼容性方案及優化