深入理解CSS @font-face性能優(yōu)化

本文主要介紹字體加載優(yōu)化的常用策略,大部分內(nèi)容為引用和翻譯。
一、 font-face基本用法
font-face的基本用法想必大家都是知道的,基本上就是類似這樣:
@font-face { font-family: Lato; src: url('font-lato/lato-regular-webfont.woff2') format('woff2'), url('font-lato/lato-regular-webfont.woff') format('woff'), url(font-lato/lato-regular-webfont.ttf) format("opentype"); } p { font-family: Lato, serif; }
這樣就可以使我們的網(wǎng)頁(yè)用上自定義字體了。 除了font-family 和 src屬性之外,還擁有font-style以及font-weight屬性。 src可以指定多種字體,會(huì)按順序依次適用,比如上面的示例中會(huì)先加載woff2字體,如果失敗再加載woff字體,否則加載opentype字體。 src所支持的字體可以有以下類型:
src參數(shù)帶不帶引號(hào)都可以,參數(shù)的格式不同含義也不盡相同,比如下面:
src: url(fonts/simple.woff); /* 加載simple.woff,地址相對(duì)于樣式表的地址 */ src: url(/fonts/simple.woff); /* 加載simple.woff,地址是網(wǎng)站的絕對(duì)地址 */ src: url(fonts/coll.otc#foo); /* 從coll.otc字符集中加載foo字體 */ src: url(fonts/coll.woff2#foo); /* 從coll.woff2字符集中加載foo字體 */ src: url(fonts.svg#simple); /* 加載id 為'simple'的SVG字體 */
src中加載的字體地址受跨域的約束,如果想跨域加載字體,需要設(shè)置CORS。
這就是font-face的最基礎(chǔ)的用法。 接下來(lái)我們會(huì)進(jìn)一步分析font-face的用法,并盡可能的找出優(yōu)化策略。
二、 什么時(shí)候會(huì)下載字體?
上面講了字體的基本知識(shí),那你有沒(méi)有想過(guò),字體是在什么時(shí)候下載的呢?當(dāng)我們僅僅在CSS中定義如下樣式的時(shí)候, 頁(yè)面加載,字體會(huì)自動(dòng)下載嗎?
@font-face { font-family: Lato; src: url('font-lato/lato-regular-webfont.woff2') format('woff2'), url('font-lato/lato-regular-webfont.woff') format('woff'), url(font-lato/lato-regular-webfont.ttf) format("opentype"); }
很遺憾,字體并不會(huì)下載。 通常情況 下,只有當(dāng)我們的頁(yè)面元素用到了font-face中定義的字體的情況下,才會(huì)下載對(duì)應(yīng)的字體。
注意: 這里我們說(shuō)了是通常情況,這是因?yàn)?,IE8在只要是定義了font-face,即使頁(yè)面元素沒(méi)有使用對(duì)應(yīng)的字體,也會(huì)下載。
在其它瀏覽器中也不盡相同,
比如在 Firefox 和 IE 9+ 中,遇到如下情況也會(huì)下載字體:
html
<div id="test"></div>
css
#test { font-family: Lato; }
有什么特別之處呢? 你可能注意到了,這個(gè)元素雖然使用到了font-family: Lato樣式,但是這個(gè)元素并沒(méi)有任何文本?。。?!。 按照我們的理想情況,應(yīng)該是,只有有文字內(nèi)容才會(huì)去下載字體嘛。 而這就是Chrome, Safari (WebKit/Blink 等)瀏覽器的行為。
Chrome, Safari (WebKit/Blink 等)瀏覽器只有在如下類似情況才會(huì)去下載字體:
html
<div id="test">這里是有文本的哦</div>
css
#test { font-family: Lato; }
所以總結(jié)一下,不同瀏覽器下載字體的策略:
- IE8 只要定義了font-face,就會(huì)去下載字體,不論實(shí)際有沒(méi)有應(yīng)用該字體。
- Firefox, IE 9+ 只有定義了font-face 并且頁(yè)面有元素應(yīng)用了該字體,就會(huì)去下載,不論該元素是否有文本內(nèi)容。
- Chrome, Safari 只有定義了font-face 并且頁(yè)面有元素應(yīng)用了該字體,并且該元素有文本內(nèi)容,才會(huì)去下載字體。
那你可能會(huì)問(wèn)了,如果我們的DOM元素是通過(guò)動(dòng)態(tài)插入的呢?比如:
var el = document.createElement('div'); el.style.fontFamily = 'open_sansregular'; document.body.appendChild(el); el.innerHTML = 'Content.';
答案是一樣的,它的下載策略如下:
var el = document.createElement('div'); el.style.fontFamily = 'open_sansregular'; /* 到這里,IE8就會(huì)開(kāi)始下載字體 */ document.body.appendChild(el); /* 只有到這里,F(xiàn)irefox, IE 9+ 才會(huì)開(kāi)始下載字體 */ el.innerHTML = 'Content.'; /* 只有到這里,Chrome, Safari 才會(huì)開(kāi)始下載字體 */
三、 FOIT(Flash of Invisible Text)
FOIT是瀏覽器在加載字體的時(shí)候的默認(rèn)表現(xiàn)形式,也就是在字體加載過(guò)程中,頁(yè)面是看不到文本內(nèi)容的。在現(xiàn)代瀏覽器中,F(xiàn)OIT會(huì)導(dǎo)致這種現(xiàn)象出現(xiàn)至多3秒。FOIT會(huì)導(dǎo)致很差的用戶體驗(yàn),這是我們需要盡量去避免的。
四、 FOUT(Flash of Unstyled Text) 與 font-display屬性
FOUT意思是在字體加載過(guò)程中使用默認(rèn)的系統(tǒng)字體,字體加載完后顯示加載的字體,如果超過(guò)了FOIT(3s)字體還沒(méi)加載,則繼續(xù)使用默認(rèn)的系統(tǒng)字體。
IE瀏覽器和Edge不會(huì)等待FOIT超時(shí)才顯示默認(rèn)字體,會(huì)立即顯示默認(rèn)字體。FOUT比FOIT好,但是需要注意它引起的reflow.
那么要想使瀏覽器有FOUT行為,我們需要在設(shè)置@font-face的時(shí)候給它加一個(gè)屬性:font-display。 font-display默認(rèn)是auto, 可選屬性與含義如下:
- auto. The font display policy is user-agent-defined.
- block. Gives the font face a short block period (3s is recommended in most cases) and an infinite swap period.
- swap. Gives the font face an extremely small block period (100ms or less is recommended in most cases) and an infinite swap period.
- 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.
一般設(shè)置成fallback和optional即可。
五、 preload
在頁(yè)面加入下面這個(gè)代碼以便更快的加載字體:
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
通常和最基本的字體用法配合使用
六、 字體轉(zhuǎn) BASE64URI
這種方法就是將@font-face中定義字體時(shí)的路徑直接改為字體的base64編碼。
優(yōu)點(diǎn): 這種做法的優(yōu)點(diǎn)是不會(huì)產(chǎn)生FOIT和FOUT。所以也不會(huì)有reflow和repaint. 缺點(diǎn): 字體轉(zhuǎn)成base64也會(huì)很大,會(huì)影響頁(yè)面首次加載速度。不支持逗號(hào)分隔的形式加載多種格式的字體,只能加載一種格式字體。這導(dǎo)致你為了盡可能保證所有瀏覽器都可以兼容,通常會(huì)指定為woff格式,因?yàn)閣off格式兼容性好,但是卻沒(méi)法使用更小體積的woff2格式,因?yàn)閣off2格式兼容性差點(diǎn)。
七、異步加載BASE64格式URI字體
這種方法就是通過(guò)異步的方式插入帶有BASE64格式URI字體的CSS鏈接。
八、使用Font Load API + FOUT + class切換
這種方式是期初并不使用用到@font-face的class,然后用Font Load API加載我們想用的字體,然后切換相應(yīng)的CSS即可。Font Load API是原生的API:
document.fonts.load('1em open_sansregular') .then(function() { var docEl = document.documentElement; docEl.className += ' open-sans-loaded'; }); .open-sans-loaded h1 { font-family: open_sansregular; }
當(dāng)然這種方法需要考慮瀏覽器兼容性的問(wèn)題。
九、 FOFT(Flash of Faux Text)
FOFT會(huì)把字體的加載分成多個(gè)部分,首先加載羅馬網(wǎng)絡(luò)字體,然后會(huì)在加載真實(shí)的粗體和斜體的時(shí)候立即使用font-synthesis屬性渲染粗體和斜體的變體。
這種方法是基于[ 使用Font Load API + FOUT + class切換
]這種方式的,非常適合加載同一種字體但是不同粗細(xì),字形的場(chǎng)景,比如羅馬、粗體、斜體、粗斜體等。我們將這些字體分成2階段: 第一階段是羅馬字體,然后立即渲染人造粗體和斜體,最后(第二階段)用真實(shí)字體替代。這里面還可以使用sessionStorage優(yōu)化訪問(wèn)重復(fù)視圖的場(chǎng)景。
十、CRITICAL FOFT
CRITICAL FOFT和標(biāo)準(zhǔn)的FOFI的唯一區(qū)別就在于第一階段羅馬字體的加載,CRITICAL FOFT不會(huì)加載羅馬字體的全集,只會(huì)加載它的一個(gè)子集(比如A-Za-z0-9),全集會(huì)在第二階段加載。
十一、CRITICAL FOFT WITH DATA URI
這個(gè)和CRITICAL FOFT的唯一區(qū)別就是羅馬子集字體的加載方式,前面是用Font Load API完成了,這里會(huì)將馬子集字體硬編碼成BASE64 URI的形式加載。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
- 本文介紹了css3的屬性@font-face的使用方法,以及在@fant-face中使用字體化圖標(biāo),有相同需求的小伙伴,自己參考下。2014-12-12
CSS3用@font-face實(shí)現(xiàn)自定義英文字體
傳說(shuō)中的CSS3基本上什么都可以,那么CSS3中可不可以自定義英文字體呢?答案是非常可以。用@font-face即可實(shí)現(xiàn)自定義英文字體,下面有個(gè)不錯(cuò)的示例,感興趣的朋友可以了解下2013-09-23什么是@font-face及font-face如何在css中使用
@ font-face的是一個(gè)CSS規(guī)則,允許你輸入自己的字體出現(xiàn)在網(wǎng)站上,即使在特定的字體在訪問(wèn)者的計(jì)算機(jī)上沒(méi)有安裝,它也可以辦得到,在使用字體方面它真的很重要,您可以使用任2013-02-26CSS @font-face屬性實(shí)現(xiàn)在網(wǎng)頁(yè)中嵌入任意字體
下面要講的是如何只通過(guò)CSS的@font-face屬性來(lái)實(shí)現(xiàn)在網(wǎng)頁(yè)中嵌入任意字體。2009-12-11css常用樣式font設(shè)置字體的多種變換(實(shí)例詳解)
這篇文章主要介紹了css常用樣式font設(shè)置字體的多種變換,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-19css中引入指定字體@font-face兼容各瀏覽器的問(wèn)題
這篇文章主要介紹了css中引入指定字體@font-face兼容各瀏覽器的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-08