自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何避免由 Web 字體引起的布局偏移

開發(fā) 前端
這篇文章我們將探索令人驚訝的復(fù)雜文本渲染世界,以及一些解決無(wú)樣式文本閃爍的技術(shù)。

前言?

一些布局上的完全加載前后的變化很容易解決:為動(dòng)態(tài)元素預(yù)先分配正確的空間,在圖像上使用寬度和高度屬性,并優(yōu)先考慮 HTML 文檔中的可見元素。但是,導(dǎo)致布局偏移的還有一個(gè)難以解決的問(wèn)題:無(wú)樣式文本 (FOUT) 的閃爍。

這篇文章我們將探索令人驚訝的復(fù)雜文本渲染世界,以及一些解決無(wú)樣式文本閃爍的技術(shù)。

為什么字體會(huì)導(dǎo)致布局變化??

意外的布局變化(頁(yè)面內(nèi)容在沒(méi)有用戶交互的情況下移動(dòng))不利于用戶體驗(yàn)。下載網(wǎng)絡(luò)字體時(shí),當(dāng)字體題發(fā)生變化時(shí),會(huì)導(dǎo)致包含元素(例如<div>,段落或段落)的大小發(fā)生變化,從而導(dǎo)致布局發(fā)生變化。當(dāng) Web 字體的字體高度或段落長(zhǎng)度與系統(tǒng)字體相比不同時(shí),就會(huì)出現(xiàn)這種情況。布局頁(yè)面時(shí),瀏覽器將使用后備字體的尺寸和屬性來(lái)確定包含元素的大小,即使你已聲明 Web 字體以阻止系統(tǒng)字體font-display: block!

「兩種不同的字體是可能會(huì)導(dǎo)致布局發(fā)生變化的,但不是一定,這主要取決于字體的字體高度。」

如何避免?

我們現(xiàn)階段的網(wǎng)頁(yè)為了滿足用戶的審美往往會(huì)使用一些特殊字體,但與此同時(shí)也會(huì)帶來(lái)一些體驗(yàn)上的問(wèn)題,最常見的就是頁(yè)面的加載速度以及文本閃爍等。所以我們有必要對(duì)字體進(jìn)行一些優(yōu)化操作來(lái)滿足我們“日益挑剔”的用戶。

font-display

最粗暴的解決方案是只需要一行CSS代碼就能夠解決。

font-display: optional;

為什么說(shuō)只需要這一行代碼就能夠解決呢,因?yàn)槿绻?Web 字體在呈現(xiàn)文本時(shí)不可用(加上 100 毫秒),它會(huì)告訴瀏覽器使用備用系統(tǒng)字體。這意味著在未緩存的頁(yè)面加載時(shí),可能會(huì)使用備用字體,但所有后續(xù)頁(yè)面加載都應(yīng)使用 Web 字體呈現(xiàn),因?yàn)樗鼘⒈幌螺d并在緩存中可用。

它一共有以下幾個(gè)屬性:

  • 「auto:」字體顯示策略由用戶代理
  • 「block:」為字體提供一個(gè)短暫的阻塞周期和無(wú)限的交換周期,在等待網(wǎng)絡(luò)字體時(shí)隱藏文本最多三秒鐘,并在加載時(shí)始終交換網(wǎng)絡(luò)字體
  • 「swap:」為字體提供一個(gè)非常小的阻塞周期和無(wú)限的交換周期,盡快顯示文本,并在加載時(shí)始終交換網(wǎng)絡(luò)字體
  • 「fallback:」為字體提供一個(gè)非常小的阻塞周期和短暫的交換周期,隱藏文本最多 100 毫秒,然后僅在三秒內(nèi)加載時(shí)交換網(wǎng)絡(luò)字體
  • 「optional:」為字體提供一個(gè)非常小的阻塞周期,并且沒(méi)有交換周期,隱藏文本最多 100 毫秒,然后僅使用可用的網(wǎng)絡(luò)字體,從不交換

上面這樣解釋如果還不太明白的話,可以看看下面這張圖:

「Optional 是唯一保證不發(fā)生布局偏移的字體顯示值」

不幸的是,系統(tǒng)字體不一定是最好的設(shè)計(jì),并且它們?cè)诟鱾€(gè)操作系統(tǒng)之間并不一致。大多數(shù)設(shè)計(jì)師一想到向用戶展示一個(gè)備用系統(tǒng)字體就會(huì)畏縮。接下來(lái)介紹各種優(yōu)化以更快地將字體文件傳送到瀏覽器,允許使用任何字體顯示選項(xiàng),但顯示系統(tǒng)字體的風(fēng)險(xiǎn)最小,或者用于optional: 以外的選項(xiàng)而不觸發(fā)布局轉(zhuǎn)換。

優(yōu)化字體文件

優(yōu)化網(wǎng)絡(luò)字體有兩種關(guān)鍵方法:子集和格式。

子集字體

許多字體將具有來(lái)自多個(gè)字母的字形(字形是單個(gè)字符,例如a或&)如果你僅以拉丁字母 (a - Z) 提供并且不使用連字(如é),那么這些字形表示您的字體文件中浪費(fèi)的字節(jié)。

從此字體中刪除非拉丁字符會(huì)產(chǎn)生woff2一個(gè)大小為六分之一的文件。

字體格式

各主流設(shè)備基本都支持 woff2 字體格式,因此網(wǎng)站中沒(méi)有必要再引入多種不同格式的字體了。一般地,建議只引入 woff2 就好了,既可以保持代碼的簡(jiǎn)潔性,又可以減少上傳到你服務(wù)器的文件。

加載更少的字體

雖然我們會(huì)將字體轉(zhuǎn)換成woff2格式,但文件大小依然有好幾百K,有時(shí)甚至是幾M,字體文件的大小也會(huì)影響頁(yè)面整體的渲染速度。有些時(shí)候我們只需要一些極少數(shù)的文字用于特殊字體,那我們就沒(méi)必要將一整個(gè)字體文件引入了。

提取字體

當(dāng)我們遇到上面這種情況時(shí),千萬(wàn)不要將一整個(gè)字體包引入進(jìn)去,這將極大地浪費(fèi)網(wǎng)絡(luò)帶寬,從而影響頁(yè)面的加載。這里推薦使用font-spider 字蛛來(lái)提取文字。

  • 安裝font-spider
npm install font-spider -g
  • 提取

我們還是以上面那段詩(shī)句為例,那里我們用的是漢儀旗黑.woff2字體文件。這里還是經(jīng)過(guò)縮小文字庫(kù)之后的大概是32K

我們?cè)僭陧?xiàng)目目錄下執(zhí)行以下命令

font-spider index.html

這時(shí)會(huì)生成一個(gè).font-spider目錄,并將提取后的字體文件放在該目錄下?,F(xiàn)在的字體文件大概就只有10K,比之前的體積小了好幾倍。

使用系統(tǒng)字體

Web 字體很受歡迎,因?yàn)樗鼈冊(cè)试S設(shè)計(jì)人員在瀏覽器中保持一致的外觀和感覺(jué)。如果不需要,系統(tǒng)字體將是呈現(xiàn)文本的最快方法。如果當(dāng)前的Web字體接近系統(tǒng)字體,您可以使用Monica的Font Style Matcher來(lái)調(diào)整字體設(shè)置,直到獲得近乎完美的匹配。

使用系統(tǒng)字體意味著文本將盡可能早地呈現(xiàn)。我們現(xiàn)在還擁有使字體與操作系統(tǒng)匹配的方法,這可能比以前的備用選項(xiàng)(如 Arial 和 Helvetica)更具吸引力。為此,我們需要按特定順序列出所有操作系統(tǒng)的系統(tǒng)字體:

body {
font-family: -apple-system, BlinkMacSystemFont,
"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
"Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
}

快速交付字體文件

很明顯,我們?yōu)榱舜_保字體快速且正確地應(yīng)用在我們網(wǎng)頁(yè)上,我們必須讓瀏覽器盡快下載我們的字體文件,在我們自己的CDN上托管字體將獲得最佳性能。

使用CDN托管

一般來(lái)說(shuō),我們應(yīng)該提供我們服務(wù)器中的字體以避免連接到第三方服務(wù)器的成本,這對(duì)于高延遲連接尤其重要。使用第三方服務(wù)意味著您的字體將被延遲。最好的情況是您直接從另一個(gè)主機(jī)名(例如fonts.gstatic.com)請(qǐng)求字體文件,這會(huì)產(chǎn)生連接成本——DNS 查找、TCP 連接和 TLS 協(xié)商。最壞的情況是多跳,例如從fonts.googleapis.com加載引用fonts.gstatic.com上的文件的 CSS 文件,會(huì)導(dǎo)致兩次連接損失。所以我們一般會(huì)將一些字體文件等靜態(tài)資源托管在我們自己的CDN服務(wù)器上,以此來(lái)加快資源的下載速度。

緩存字體

字體可以緩存在兩個(gè)地方:「客戶端和CDN」。客戶端上的緩存對(duì)于會(huì)話中的導(dǎo)航很重要,并且應(yīng)該以避免重新驗(yàn)證請(qǐng)求的方式完成。重新驗(yàn)證請(qǐng)求 (if-not-modified和if-modified-since) 將阻止瀏覽器使用字體文件,直到它驗(yàn)證它在服務(wù)器上沒(méi)有更改。字體很少改變,所以我們應(yīng)該如下實(shí)現(xiàn)一個(gè)緩存頭,并在字體改變時(shí)更新文件名來(lái)破壞緩存:

cache-control: max-age=31536000,immutable

這告訴瀏覽器他們可以保留字體長(zhǎng)達(dá)一年并且不需要重新驗(yàn)證( Firefox 和 Safariimmutable 支持,Chrome 應(yīng)該自動(dòng)避免重新驗(yàn)證請(qǐng)求)。避免將 ETag 添加到這些響應(yīng)中,因?yàn)樗鼈兛赡軙?huì)強(qiáng)制重新驗(yàn)證。

還要檢查您的 Content Delivery Network 配置是否可以將字體文件存儲(chǔ)在緩存中,較舊的配置可能不包含.woff2擴(kuò)展名,從而導(dǎo)致原始命中并減慢響應(yīng)速度。

使用預(yù)加載

一般來(lái)講瀏覽器不會(huì)隨便地去下載字體文件,它們會(huì)等到渲染樹構(gòu)建完成后才能知道需要哪些字體。這意味著僅在瀏覽器下載并解析 HTML 和 CSS 時(shí),即在呈現(xiàn)文本之前,才請(qǐng)求 Web 字體。「但需要注意的是,內(nèi)聯(lián) CSS 不需要網(wǎng)絡(luò)請(qǐng)求,這意味著我們的字體可以在頁(yè)面加載的早期獲取。」

渲染樹的構(gòu)建過(guò)程會(huì)阻塞Web字體的請(qǐng)求。

但是如果我們確定頁(yè)面文本的渲染肯定會(huì)用到一些網(wǎng)絡(luò)字體時(shí),我們可以使用preload讓瀏覽器提前下載字體文件。

<link rel="preload" href="./public/fonts/漢儀旗黑.woff2" crossorigin="anonymous" type="font/woff2">

當(dāng)瀏覽器解析這行 HTML 時(shí),它會(huì)立即發(fā)送一個(gè)對(duì)字體文件的高優(yōu)先級(jí)請(qǐng)求。

「但是需要注意的是,預(yù)加載的請(qǐng)求會(huì)占用其它請(qǐng)求的帶寬,所以我們?cè)谑褂眠^(guò)程需要考慮清楚是否值得這么做?!?/p>

將字體轉(zhuǎn)為Base64

還有一種常用的方法是將字體作為 Base64 字符串嵌入到 CSS 中,從而無(wú)需額外的字體請(qǐng)求并確保在呈現(xiàn)文本時(shí)字體可用。

但這個(gè)方法也不是絕對(duì)的好方法,它只適合一些小型字體文件,例如上面提到的使用font-spider提取后的字體文件,并且該字體文件足夠小,因?yàn)閷⒆煮w文件轉(zhuǎn)化為Base64字符串往往會(huì)增加體積。

一般來(lái)講它有以下缺點(diǎn):

  1. 字體文件是壓縮的二進(jìn)制對(duì)象,編碼為 Base64 字符串會(huì)顯著增加大小。CSS 包的 gzip 或 brotli 壓縮并不能完全彌補(bǔ)這種膨脹。
  2. 字體將被發(fā)送到每個(gè)瀏覽器,即使有的瀏覽器不能使用
  3. 字體很少更改,但 CSS 經(jīng)常更改,這將降低字體的緩存效率,因?yàn)槊看?CSS 更改都會(huì)使整個(gè)包無(wú)效
  4. 膨脹 CSS 大小幾乎肯定會(huì)延遲頁(yè)面渲染

使用f-mods減少布局偏移

F-mods 是對(duì)字體描述符規(guī)范的提議更新,其中包括四個(gè)新的描述符:

  • 「ascent-override (%)」 : 覆蓋分配給上升器的大小
  • 「descent-override (%)」 : 覆蓋分配給下降者的行高
  • 「line-gap-override (%)」 : 覆蓋行間距
  • 「advance-override (#)」 : 為每個(gè)字符設(shè)置一個(gè)額外的提前量,以幫助匹配行寬并防止單詞溢出

前三個(gè)都影響線的高度:線框高度 = 上升 + 下降 + 線間隙。基線位置 = 線框頂部 + 線間隙 / 2 + 上升。

這四個(gè)描述符的組合允許我們通過(guò)告訴瀏覽器在下載 Web 字體之前字符將占用多少空間來(lái)覆蓋備用字體的布局以匹配 Web 字體。

f-mods 只真正修改垂直間距和定位。這意味著仍然需要處理字符間距和字母間距,否則可能會(huì)在不同的點(diǎn)出現(xiàn)斷行的單詞,從而導(dǎo)致元素高度發(fā)生變化,從而導(dǎo)致布局發(fā)生變化。但是@font-face 聲明中沒(méi)有l(wèi)etter-spacingandword-spacing屬性,因此我們必須在主體或元素上聲明。

@font-face {
font-family: custom-font;
src: url("./public/fonts/漢儀旗黑.woff2");
}
@font-face {
font-family: fallback-font;
src: local(Arial);
ascent-override: 100%;
descent-override: 20%;
line-gap-override: normal;
advance-override: 10;
}
/* 這些具體數(shù)值因字體而已,需要按照自己的字體進(jìn)行計(jì)算調(diào)整*/
body {
font-family: custom-font, fallback-font;
}
.content {
letter-spacing: -1.1px;
word-spacing: -0.2px;
}

總結(jié)?

總之,如果瀏覽器沒(méi)有及時(shí)獲取網(wǎng)絡(luò)字體,并且可以應(yīng)用font-display: optional到網(wǎng)絡(luò)字體,讓瀏覽器以備用系統(tǒng)字體呈現(xiàn)來(lái)防止布局偏移,否則的話就只能優(yōu)化我們的字體以嘗試在瀏覽器需要它們之前將它們獲取到瀏覽器:

  • 使用woff2最小化文件大小
  • 優(yōu)化字體文件
  • 加載更少的字體
  • 預(yù)加載關(guān)鍵字體
  • 在CDN上托管字體文件
  • 使用 f-mods 減少字體交換的影響
責(zé)任編輯:華軒 來(lái)源: 前端南玖
相關(guān)推薦

2018-04-10 13:02:51

HBase寫入流程數(shù)據(jù)

2013-12-12 16:28:04

Lua腳本語(yǔ)言

2024-05-29 14:26:45

2022-11-03 16:10:29

groovyfullGC

2022-10-27 21:32:34

oracle數(shù)據(jù)庫(kù)

2011-03-17 14:07:39

2011-03-17 14:21:35

2022-02-21 14:41:21

APIWeb安全

2012-07-12 10:13:35

2018-08-01 15:55:21

微軟瀏覽器Windows

2014-08-13 15:55:17

Web響應(yīng)式設(shè)計(jì)design

2016-04-08 09:24:01

脆弱代碼更新

2012-03-31 10:12:55

CSSWEB

2019-03-26 08:52:51

2021-08-02 13:08:56

高并發(fā)服務(wù)

2018-05-24 13:58:03

LinuxGoogle Web字Font Finder

2015-03-15 18:47:09

2024-07-03 09:13:26

SwiftUI修飾符框架

2012-11-08 09:43:12

編程語(yǔ)言技術(shù)開發(fā)代碼重構(gòu)

2023-07-25 16:47:17

Serverless架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)