web安全字体
?
webfont解剖
- Unicode字體可以包含數(shù)以千計(jì)字形
- 有四個(gè)字體格式: WOFF2, WOFF, EOT, TTF
- 一些字體格式需要使用GZIP壓縮?
一個(gè)web字體是字形的集合,且每個(gè)字形是一個(gè)描述了一個(gè)字母亦或符號(hào)的矢量圖。
所以,一個(gè)字體文件的大小由兩個(gè)因素決定:每個(gè)字形矢量路徑的復(fù)雜程度和每個(gè)字體所包含的字形數(shù)量。
例如,Open Sans, 最流行的web字體之一, 包含了897個(gè)字形,包含了拉丁,希臘和古代斯拉夫語(yǔ)字母。
當(dāng)選擇一個(gè)字體的時(shí)候,重要的是考慮哪些字符集被支持。
例如,?Google’s Noto font family?目標(biāo)是支持世界上所有的語(yǔ)言. 但是,注意Noto的大小,因?yàn)榘怂械恼Z(yǔ)言,所以壓縮后大小是130MB+。
Web字體格式
網(wǎng)上如今四個(gè)web字體格式:?EOT,?TTF,?WOFF, 和?WOFF2.
不幸的是,雖然有很多的選擇,但是沒(méi)有一個(gè)字體是可以在舊的瀏覽器和新的瀏覽器上通用的:EOT只適用于IE,TTP部分被IE支持。WOFF享有最廣泛的支持但是在老的瀏覽器中不必支持,并且對(duì)于很多新的瀏覽器真在添加對(duì)于WOFF 2.0的支持。
所以,這意味著我們需要使用多個(gè)字體格式來(lái)保持良好的用戶(hù)體驗(yàn):
- 在支持WOFF 2.0的瀏覽器中使用WOFF 2.0 變體
- 在大多數(shù)瀏覽器中使用WOFF字體
- 在老的安卓(低于4.4)瀏覽器中使用TTF變體
- 在老的IE(低于IE9)中使用EOT變體?
使用壓縮來(lái)減少字體大小
A font is a collection of glyphs, each of which is a set of paths describing the letter form. The individual glyphs are, of course, different, but they nonetheless contain a lot of similar information that can be compressed with GZIP, or a compatible compressor:
- EOT, 和 TTF 格式默認(rèn)沒(méi)有壓縮:確保你的服務(wù)器使用了GZIP壓縮?
- WOFF 有內(nèi)置的壓縮?- 確保你的WOFF壓縮器使用了最優(yōu)化的設(shè)置。
- WOFF2 使用了用戶(hù)預(yù)定義和壓縮算法來(lái)減少相對(duì)于其他字體格式約30%的文件大小
值得注意的是一些字體格式包括了額外的信息——比如font hitting和kerning信息,這些可能是不必要的,所以可以進(jìn)行深入優(yōu)化。
查看你的字體編譯器可操作的選項(xiàng),如果你可以?xún)?yōu)化上面的內(nèi)容,進(jìn)行優(yōu)化,并在不同的瀏覽器中查看效果。
Note
- 可以使用?Zopfli compression?來(lái)壓縮EOT, TTF,和?WOFF 字體格式. Zopfli 是一個(gè) zlib兼容的壓縮器,壓縮的內(nèi)容比gzip壓縮后還要小約5%。
使用 @font-face定義字體
- 使用format()定義不同的字體格式
- 使用大量的子集提高性能: 提供大量可選的子集可以讓舊的瀏覽器兼容?
- 減少樣式化的字體變體來(lái)提高頁(yè)面和文字渲染效果?
?css語(yǔ)句@font-face定義特殊的字體資源的位置,字體樣式等。
字體樣式選擇
每個(gè) @font-face 聲明提供了font family的名字,字體屬性的什么和特殊字體來(lái)源地址的聲明。
@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome.woff2') format('woff2'), url('/fonts/awesome.woff') format('woff'),url('/fonts/awesome.ttf') format('ttf'),url('/fonts/awesome.eot') format('eot'); }@font-face {font-family: 'Awesome Font';font-style: italic;font-weight: 400;src: local('Awesome Font Italic'),url('/fonts/awesome-i.woff2') format('woff2'), url('/fonts/awesome-i.woff') format('woff'),url('/fonts/awesome-i.ttf') format('ttf'),url('/fonts/awesome-i.eot') format('eot'); }?
上面一個(gè)?Awesome Font?字體的兩個(gè)表現(xiàn)形式類(lèi)型:正常和斜體,每個(gè)都提供了一系列的不同字體資源設(shè)置。
每個(gè)src描述符包括了一個(gè)按照優(yōu)先順序排序的,用逗號(hào)進(jìn)行分隔的資源列表:
- local()?表明我們可以使用哪些本地的字體?
-
url()?指定我們加載哪些外部字體,允許我們使用format()來(lái)指代字體的格式?
Note
- 除非你指向系統(tǒng)的默認(rèn)資源,除非很少有本地的字體資源,特別是對(duì)手機(jī)設(shè)備而言,不可能在內(nèi)部安裝了額外的字體。所以,你總是需要提供一個(gè)額外的字體位置清單。
瀏覽器按照順序執(zhí)行,上例瀏覽器執(zhí)行如下:
- 如果字體格式存在,在初始化和下載字體之間檢查瀏覽器是否支持,如果不支持,進(jìn)入下一個(gè)外部字體選項(xiàng)檢查?
- 如果字體格式不存在,瀏覽器下載資源?
Note
- 外部字體加載的順序十分重要,因?yàn)闉g覽器是按照這個(gè)順序依次執(zhí)行的。
Unicode-range 子集
我們可以將一個(gè)大的字體設(shè)置成小的子集(例如拉丁,希臘和斯拉夫字母等),并且只是加載這個(gè)子集來(lái)渲染頁(yè)面上的字體
?
這個(gè)?unicode-range descriptor?允許我們指定一個(gè)逗號(hào)隔開(kāi)的數(shù)據(jù)集合, 數(shù)據(jù)可以是下面三種形式中的任何一種:
- Single codepoint (e.g. U+416)
- Interval range (e.g. U+400-4ff): indicates the start and end codepoints of a range
- Wildcard range (e.g. U+4??): ‘?’ characters indicate any hexadecimal digit
例如我們可以將Awesome Font設(shè)置成拉丁和日本語(yǔ)的子集格式,它們只有在瀏覽器需要的時(shí)候才會(huì)加載?
@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome-l.woff2') format('woff2'), url('/fonts/awesome-l.woff') format('woff'),url('/fonts/awesome-l.ttf') format('ttf'),url('/fonts/awesome-l.eot') format('eot');unicode-range: U+000-5FF; /* Latin glyphs */ }@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome-jp.woff2') format('woff2'), url('/fonts/awesome-jp.woff') format('woff'),url('/fonts/awesome-jp.ttf') format('ttf'),url('/fonts/awesome-jp.eot') format('eot');unicode-range: U+3000-9FFF, U+ff??; /* Japanese glyphs */ }Note
- Unicode-range子集設(shè)置對(duì)于亞洲語(yǔ)言非常重要,因?yàn)閬喼拚Z(yǔ)言的字形比西方語(yǔ)言要多得多,一個(gè)字形百萬(wàn)字節(jié),而不是亞洲字符的千字節(jié)。
使用unicide range子集并將文件分成字體不同樣式的變體讓我們可以更加迅速和高效的下載——用戶(hù)只需要下載子集和變體就可以,用戶(hù)不需要下載永遠(yuǎn)不會(huì)用到的字體。
但是,不是所有的瀏覽器支持unicode-range字段。一些瀏覽器忽略了unicode-range字段,并且將下載所有的字體;另一些瀏覽器壓根兒不會(huì)執(zhí)行@font-face聲明。所以,我們對(duì)于舊的瀏覽器需要“手動(dòng)設(shè)置子集”。
因?yàn)榕f的瀏覽器不夠聰明來(lái)選擇需要的字體子集并且不能合成一個(gè)合適的字體,所以我們必須回退來(lái)提供一個(gè)單一的字體資源,這個(gè)字體資源包括了所有必要的子集,并且對(duì)瀏覽器而言隱藏了其他的子集。
例如,如果網(wǎng)頁(yè)只是使用拉丁文子集。我們可以剝奪其他的字形,并且將一個(gè)指定的子集設(shè)置成單獨(dú)的資源。
- 如果unicode-range子集是被瀏覽器支持的,那么瀏覽器就會(huì)在自動(dòng)的選擇合適的子集,頁(yè)面只需要提供子集文件和在@font-face指定合適的unicode-ranges
- 如果unicode-range不是瀏覽器支持那么頁(yè)面需要隱藏所有不必要的子集——例如,開(kāi)發(fā)者必須指定需要的子集。
- 使用開(kāi)源工具?pyftsubset tool?來(lái)設(shè)置和最優(yōu)化你的子集.
- 一些字體提供商允許你在用戶(hù)自定義參數(shù)中手動(dòng)設(shè)置字體子集,你可以通過(guò)這個(gè)方法來(lái)手動(dòng)的為你的頁(yè)面創(chuàng)建需要的字體——訪問(wèn)字體提供商的頁(yè)面!
字體選擇和合成
每個(gè)字體家族都是包含很多樣式的字體變體(例如常規(guī),加粗,斜體等等),并且每一種字體變體都有字體權(quán)重設(shè)置,所以,這將導(dǎo)致了很多不同的字形——例如,不同空格,字體大小都將導(dǎo)致同一個(gè)字形變得不同。
例如,上面的圖形展示了一個(gè)字體在三種不同的權(quán)重下的表現(xiàn):400(普通),700(加粗),900(額外加粗)。
所有的在三個(gè)標(biāo)準(zhǔn)之間的權(quán)重(灰色顯示的)將通過(guò)瀏覽器自動(dòng)的適應(yīng)最貼近的三種標(biāo)準(zhǔn)變體。
上述邏輯同樣適用于斜體字體,但是要記住,字體變形數(shù)量使用越少越好!
@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 400;src: local('Awesome Font'),url('/fonts/awesome-l.woff2') format('woff2'), url('/fonts/awesome-l.woff') format('woff'),url('/fonts/awesome-l.ttf') format('ttf'),url('/fonts/awesome-l.eot') format('eot');unicode-range: U+000-5FF; /* Latin glyphs */ }@font-face {font-family: 'Awesome Font';font-style: normal;font-weight: 700;src: local('Awesome Font'),url('/fonts/awesome-l-700.woff2') format('woff2'), url('/fonts/awesome-l-700.woff') format('woff'),url('/fonts/awesome-l-700.ttf') format('ttf'),url('/fonts/awesome-l-700.eot') format('eot');unicode-range: U+000-5FF; /* Latin glyphs */ }?
上面的例子聲明了一個(gè)?Awesome Font?家族字體,包含了拉丁字形,但是擁有兩種不一樣的權(quán)重:normal(400)和blod(700)。字體不同的形式實(shí)現(xiàn)的原理是什么呢?
- 如果給出的字體權(quán)重不是標(biāo)準(zhǔn)的(400,700和900),那么將隨瀏覽器匹配最接近標(biāo)準(zhǔn)的字體形式。
- 如果字體斜體匹配沒(méi)有發(fā)現(xiàn)(例如,我們沒(méi)有在上例中聲明任何的斜體變形),那么瀏覽器近合成它的自有的字體變形。
上面的例子解釋了實(shí)際斜體和瀏覽器合成的斜體之間的不同(字體是Open-Sans字體)。
你可以在結(jié)果中看見(jiàn)顯著的不同,不同的瀏覽器合成字體不同并且不同的字體之間合成的字體也不同。
Note
- 為了最好的用戶(hù)體驗(yàn),我們應(yīng)該盡量不要使用字形變體,我們最好指定字體的位置讓頁(yè)面來(lái)下載它們??偠灾?#xff0c;使用瀏覽器合成的變體必須非常小心。
優(yōu)化下載和渲染
- 字體加載請(qǐng)求會(huì)在渲染樹(shù)(the render tree)被創(chuàng)建之后,這可能導(dǎo)致字體渲染被延遲。
- 字體加載API同樣也允許我們實(shí)現(xiàn)用戶(hù)自定義的字體加載和渲染政策來(lái)重寫(xiě)和替代默認(rèn)的字體延遲加載
- Font inlining 允許我們?cè)谂f的瀏覽器中重新書(shū)寫(xiě)字體加載形式
一個(gè)完整的web字體包含了所有形式的變體,和所有的字形,但是有些字形和字體的變體我們可能不需要,導(dǎo)致下載完整的web字體需要多個(gè)百萬(wàn)字節(jié)。
所以使用@font-face是我們可以加載指定范圍的web字體,使用unicode 子集,獨(dú)特的字體變形等等。
給出這些申明后瀏覽器可以加載指定的字體來(lái)進(jìn)行渲染,雖然很方便,但是如果我們不小心的話,會(huì)導(dǎo)致在渲染時(shí)產(chǎn)生障礙——這些是我們需要避免的!
web字體渲染方式
我們知道字體的渲染必須在瀏覽器創(chuàng)建了渲染樹(shù)(就是DOM樹(shù)和CSSOM樹(shù))之后,所以,也就是說(shuō)字體渲染必須等到所有的資源都被抓取之后
- 當(dāng)樹(shù)DOM樹(shù)被渲染的時(shí)候字體被請(qǐng)求,說(shuō)明了字體變體被渲染到指定的文本上。
- 如果瀏覽器不可以獲得字體嗎,那么將不會(huì)渲染任何的文本像素
- 一旦瀏覽器可以獲得字體,瀏覽器將會(huì)渲染文本像素
不同的瀏覽器在渲染的時(shí)候執(zhí)行的操作不一樣:
- Safari 在文本下載全部完成之后才進(jìn)行文本渲染
- Chrome 和 Firefox 在你使用一個(gè)回退字體時(shí),進(jìn)行三秒鐘的字體渲染, 并且一旦字體下載完成,瀏覽器用剛下載的字體再次進(jìn)行渲染
- IE馬上渲染回退字體如果請(qǐng)求的字體不可獲得,并且一旦字體加載全部完成之后在進(jìn)行再次渲染 。
不同的人有不同的喜好——有些人喜歡馬上進(jìn)行渲染有些人喜歡在回退字體加載后進(jìn)行再次渲染——我們不做任何的評(píng)論,但是我們關(guān)注的是在布局加載時(shí)進(jìn)行的字體渲染怎樣才能進(jìn)行優(yōu)化?
使用字體下載API來(lái)優(yōu)化字體渲染
Font Loading API?提供了一個(gè)編程腳本來(lái)定義和操作CSS字體,追蹤字體的下載進(jìn)程和重寫(xiě)字體的懶加載行為(懶加載是指在DOM樹(shù)和CSSOM樹(shù)加載完成之后才進(jìn)行字體加載渲染的行為)。
例如,如果我們確保一個(gè)特殊的字體變形會(huì)被請(qǐng)求,我們可以定義它并且告訴瀏覽器來(lái)初始化即時(shí)加載字體資源行為:
var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {style: 'normal', unicodeRange: 'U+000-5FF', weight: '400' });font.load(); // don't wait for render tree, initiate immediate fetch!font.ready().then(function() {// apply the font (which may rerender text and cause a page reflow)// once the font has finished downloadingdocument.fonts.add(font);document.body.style.fontFamily = "Awesome Font, serif";// OR... by default content is hidden, and rendered once font is availablevar content = document.getElementById("content");content.style.visibility = "visible";// OR... apply own render strategy here... });?
而且,因?yàn)槲覀兛梢詸z查字體的狀態(tài)(font status)通過(guò)check()方法,并且追蹤下載的速度,我們同樣可以定義一個(gè)自定義的策略來(lái)在我們的頁(yè)面上渲染文本,
- 我們可以知道字體可以使用時(shí)才渲染所有文本?
- 我們可以對(duì)于每一個(gè)字體設(shè)置定時(shí)器timeout?
我們可以在不同的頁(yè)面上使用不同的策略。
Note
- 字體加載API在某些瀏覽器中還尚在開(kāi)發(fā)中,可考慮使用FontLoader polyfill, 或者?webfontloader library, 來(lái)產(chǎn)生相同的效果
使用inlining來(lái)優(yōu)化渲染字體
- 在構(gòu)建CSSOM對(duì)象的時(shí)候,css樣式中匹配設(shè)備的查詢(xún)將作為首選自動(dòng)加載?
- 將字體數(shù)據(jù)嵌入css樣式表中將強(qiáng)制瀏覽器來(lái)加載字體,并且以高優(yōu)先級(jí)進(jìn)行不用等到渲染樹(shù)的完成
但是 inlining策略不夠靈活并且不允許針對(duì)不同個(gè)頁(yè)面我們來(lái)定義用戶(hù)自定義的定時(shí)器和渲染策略。為了最好的效果,將你的嵌入字體數(shù)據(jù)的css獨(dú)立成css文件,并且加載的時(shí)候設(shè)置max-age屬性,這樣當(dāng)你更新css文件的時(shí)候不用強(qiáng)迫你的用于再次下載你的字體。
Note
- 使用inlining策略! 記得上面說(shuō)的懶加載么?瀏覽器通常都是在加載DOM和形成CSSOM對(duì)象之后,形成渲染樹(shù)之后在渲染數(shù)據(jù)內(nèi)容到屏幕上的!將字體數(shù)據(jù)放在CSS中,也就是放在CSSOM對(duì)象形成之時(shí)!
使用HTTP緩存優(yōu)化你的字體再使用
字體資源是靜止的資源,所以可以再次使用,使用http緩存,為字體設(shè)置較長(zhǎng)時(shí)間的max-age。沒(méi)有必要將字體存儲(chǔ)在localStorage中,這會(huì)影響性能。
優(yōu)化總結(jié)列表
使用web字體除了會(huì)進(jìn)行下載和下載不必要的資源之外,不會(huì)影響頁(yè)面的渲染和性能!所以放心大膽使用,下面是一些優(yōu)化建議:
原文:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization?hl=en
轉(zhuǎn)載于:https://www.cnblogs.com/RachelChen/p/5452870.html
總結(jié)
- 上一篇: 孕妇梦到牛顶自己是什么意思
- 下一篇: sql中问号是干什么的??