深入理解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; }
如許就可以使我們的頁面用上自定義字體了。 除了font-family 和 src屬性之外,還擁有font-style以及font-weight屬性。 src可以指定多種字體,會按順序依次適用,比如上面的示例中會先加載woff2字體,假如失敗再加載woff字體,否則加載opentype字體。 src所支持的字體可以有以下類型:
src參數(shù)帶不帶引號都可以,參數(shù)的格式不同含義也不盡雷同,比如下面:
src: url(fonts/simple.woff); /* 加載simple.woff,地址相對于樣式表的地址 */ src: url(/fonts/simple.woff); /* 加載simple.woff,地址是網(wǎng)站的絕對地址 */ 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ǔ)的用法。 接下來我們會進(jìn)一步分析font-face的用法,并盡可能的找出優(yōu)化策略。
二、 什么時候會下載字體?
上面講了字體的基本知識,那你有沒有想過,字體是在什么時候下載的呢?當(dāng)我們僅僅在CSS中定義如下樣式的時候, 網(wǎng)頁加載,字領(lǐ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"); }
很遺憾,字體并不會下載。 通常情況 下,只有當(dāng)我們的網(wǎng)頁元素用到了font-face中定義的字體的情況下,才會下載對應(yīng)的字體。
細(xì)致: 這里我們說了是通常情況,這是由于,IE8在只要是定義了font-face,即使網(wǎng)頁元素沒有使用對應(yīng)的字體,也會下載。
在其它欣賞器中也不盡雷同,
比如在 Firefox 和 IE 9+ 中,碰到如下情況也會下載字體:
html
<div id="test"></div>
css
#test { font-family: Lato; }
有什么分外之處呢? 你可能細(xì)致到了,這個元素雖然使用到了font-family: Lato樣式,但是這個元素并沒有任何文本?。。。?。 按照我們的理想情況,應(yīng)該是,只有有筆墨內(nèi)容才會去下載字體嘛。 而這就是Chrome, Safari (WebKit/Blink 等)欣賞器的舉動。
Chrome, Safari (WebKit/Blink 等)欣賞器只有在如下類似情況才會去下載字體:
html
<div id="test">這里是有文本的哦</div>
css
#test { font-family: Lato; }
所以總結(jié)一下,不同欣賞器下載字體的策略:
IE8 只要定義了font-face,就會去下載字體,不論現(xiàn)實(shí)有沒有應(yīng)用該字體。
Firefox, IE 9+ 只有定義了font-face 并且網(wǎng)頁有元素應(yīng)用了該字體,就會去下載,不論該元素是否有文本內(nèi)容。
Chrome, Safari 只有定義了font-face 并且網(wǎng)頁有元素應(yīng)用了該字體,并且該元素有文本內(nèi)容,才會去下載字體。
那你可能會問了,假如我們的DOM元素是通過動態(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就會開始下載字體 */ document.body.appendChild(el); /* 只有到這里,F(xiàn)irefox, IE 9+ 才會開始下載字體 */ el.innerHTML = 'Content.'; /* 只有到這里,Chrome, Safari 才會開始下載字體 */
三、 FOIT(Flash of Invisible Text)
FOIT是欣賞器在加載字體的時候的默認(rèn)體現(xiàn)情勢,也就是在字體加載過程中,網(wǎng)頁是看不到文本內(nèi)容的。在當(dāng)代欣賞器中,F(xiàn)OIT會導(dǎo)致這種征象出現(xiàn)至多3秒。FOIT會導(dǎo)致很差的用戶體驗(yàn),這是我們必要盡量去避免的。
四、 FOUT(Flash of Unstyled Text) 與 font-display屬性
FOUT意思是在字體加載過程中使用默認(rèn)的體系字體,字體加載完后表現(xiàn)加載的字體,假如超過了FOIT(3s)字體還沒加載,則繼承使用默認(rèn)的體系字體。
IE欣賞器和Edge不會等待FOIT超時才表現(xiàn)默認(rèn)字體,會立即表現(xiàn)默認(rèn)字體。FOUT比FOIT好,但是必要細(xì)致它引起的reflow.
那么要想使欣賞器有FOUT舉動,我們必要在設(shè)置@font-face的時候給它加一個屬性: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
在網(wǎng)頁加入下面這個代碼以便更快的加載字體:
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
通常和最基本的字體用法配合使用
六、 字體轉(zhuǎn) BASE64URI
這種方法就是將@font-face中定義字體時的路徑直接改為字體的base64編碼。
好處: 這種做法的好處是不會產(chǎn)生FOIT和FOUT。所以也不會有reflow和repaint. 瑕玷: 字體轉(zhuǎn)成base64也會很大,會影響網(wǎng)頁首次加載速度。不支持逗號分隔的情勢加載多種格式的字體,只能加載一種格式字體。這導(dǎo)致你為了盡可能保證所有欣賞器都可以兼容,通常會指定為woff格式,由于woff格式兼容性好,但是卻沒法使用更小體積的woff2格式,由于woff2格式兼容性差點(diǎn)。
七、異步加載BASE64格式URI字體
這種方法就是通過異步的體例插入帶有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)然這種方法必要考慮欣賞器兼容性的題目。
九、 FOFT(Flash of Faux Text)
FOFT會把字體的加載分成多個部分,首先加載羅馬網(wǎng)絡(luò)字體,然后會在加載真實(shí)的粗體和斜體的時候立即使用font-synthesis屬性渲染粗體和斜體的變體。
這種方法是基于[ 使用Font Load API + FOUT + class切換
]這種體例的,特別很是適合加載統(tǒng)一種字體但是不同粗細(xì),字形的場景,比如羅馬、粗體、斜體、粗斜體等。我們將這些字體分成2階段: 第一階段是羅馬字體,然后立即渲染人造粗體和斜體,最后(第二階段)用真實(shí)字體替換。這里面還可以使用sessionStorage優(yōu)化訪問重復(fù)視圖的場景。
十、CRITICAL FOFT
CRITICAL FOFT和標(biāo)準(zhǔn)的FOFI的唯一區(qū)別就在于第一階段羅馬字體的加載,CRITICAL FOFT不會加載羅馬字體的全集,只會加載它的一個子集(比如A-Za-z0-9),全集會在第二階段加載。
十一、CRITICAL FOFT WITH DATA URI
這個和CRITICAL FOFT的唯一區(qū)別就是羅馬子集字體的加載體例,前面是用Font Load API完成了,這里會將馬子集字體硬編碼成BASE64 URI的情勢加載。
以上就是本文的悉數(shù)內(nèi)容,盼望對大家的學(xué)習(xí)有所幫助,也盼望大家多多支持圖趣網(wǎng)。
本文地址:http://pkvc.cn/tutorial/wd491.html