摘要:在字體的過程中,先用一種最接近目標字體的安全字體來顯示,等字體文件加載完后進行替換。第個方案是一種迫不得已的選擇,在用戶眼皮底下更換字體,是非常影響體驗的,好處是字體屬于異步加載,不會阻塞文本顯示。
問題
最近在做一個項目時,遇到了這樣一個問題:網(wǎng)頁大標題要用設(shè)計師指定的中文字體,該字體文件比較大,瀏覽器加載字體文件的過程中是不會顯示使用該字體的文本的,于是出現(xiàn)了初次打開網(wǎng)頁時有一段時間“No title”的BUG。
解決方案針對該問題,筆者能想到以下幾種解決方案(歡迎補充):
把文字做成png圖片,或改為路徑后做成SVG圖片,考慮做成base64內(nèi)嵌到CSS文件。
使用字體工具,將字體包中沒用到的字符刪除來減小字體文件的體積(npm上也有這樣的優(yōu)秀JS庫)。
方案1的升級版,在所有用到這個字體的文本中,把首屏出現(xiàn)的文本做成圖片,后面的文本依然使用字體包,并在打開首頁時就加載字體包。
方案2的升級版,在向服務(wù)器請求字體的時候,由服務(wù)端分析document中所有用到的字符,動態(tài)生成字體包后返回給瀏覽器端。
在loading字體的過程中,先用一種最接近目標字體的安全字體來顯示,等字體文件加載完后進行替換。
打死設(shè)計師,想用啥用啥。
方案對比與選擇由于后續(xù)的頁面內(nèi)容也有不少文本會用到該字體,且考慮今后網(wǎng)站維護成本,所以1、2兩個解決方案不適合本項目。
第3個方案最省事,做快速開發(fā)的話比較合適,但代碼復(fù)用性不高,程序也不夠健壯,例如低網(wǎng)速情況下,有可能會出現(xiàn)字體包未完全加載時用戶已經(jīng)滑到下一頁,而這一頁中有文本是使用了目標字體包從而不顯示的情況。
第4個方案需要后端開發(fā)的配合,要考慮如何判斷所有用到的字符,并且在JS向document中寫入新的字符時,要請求增量字體包,會較大程度地增加CDN服務(wù)端負擔(dān)(主要是怕跟后端開發(fā)撕逼)。
第5個方案是一種迫不得已的選擇,在用戶眼皮底下更換字體,是非常影響體驗的,好處是字體屬于異步加載,不會阻塞文本顯示。
最后一個方案成本比較高,需要搭上開發(fā)人員的下半輩子,好處是可以從根本上解決這個BUG,永訣后患。被逼急的程序員可以嘗試下。
結(jié)合項目特點,最終選擇方案5。
實現(xiàn)過程整個過程邏輯非常簡單:首先標題所用的class在CSS中被定義了一個最接近目標字體的安全字體,然后等待字體文件加載,加載完成后將標題的class換成自定義字體的class。
首先設(shè)好兩個CSS屬性,一個是用最接近目標字體的安全字體,用于默認字體,第二個是自定義字體:
/* 定義字體 */ @font-face{ font-family: Lanting_light; src: url("../res/font/goDieDesigner.woff"); } /* 安全字體,用于默認 */ .lanting_l{ font-family: Arial, Helvetica, sans-serif; } /* 自定義字體 */ .lanting_light{ font-family: "Lanting_light",Arial, Helvetica, sans-serif; }
元素設(shè)置成默認字體:
我是一段可愛的文字,啾咪~
寫一個函數(shù),用于替換元素的class,在字體文件加載完成后執(zhí)行它:
function onLoadedFont() { ele = document.getElementsByClassName("Lanting_l"); for (let i = 0; i < ele.length; i++){ ele[i].classList.add("Lanting_light"); ele[i].classList.remove("Lanting_l"); } }
接下來是整個問題的核心:如何判斷字體文件已被加載?
一個html元素,可以用監(jiān)聽load事件來判斷加載,但字體不是html元素,無法監(jiān)聽。
再來看一下需求,字體文件是從用戶打開頁面時就要開始加載了,所以只要讓字體一開始就加載,然后監(jiān)聽window.load事件就好了:
window.addEventListener("load",onLoadedFont);
PS:這里不太嚴謹,可能會有其他大體積資源加載拖慢load事件,所以大文件最好用lazyload。MDN提供了一個屬性可以判斷字體加載,但是目前兼容性還有一些問題,這里就先不用了,感興趣的可以看一下這里。小弟才疏學(xué)淺,如有大神知道其他監(jiān)聽字體文件加載的方法,還請留言告知,謝謝~
然后就是要做些什么讓字體文件一開始就去加載了,要知道不同瀏覽器什么時候會去加載一個字體,可以參考這篇文章。
在HTML中創(chuàng)建一個文本標簽,讓它去用這個需要被加載的字體,并且讓這個文本不要出現(xiàn)在視窗中:
字體
最后擦個屁股,load完成后把上述已經(jīng)被榨干剩余價值的節(jié)點刪掉:
window.addEventListener("load",function(){ let dev = document.getElementsByClassName("Lanting_light"); for (let i = 0; i < dev.length; i++){ dev[i].parentElement.removeChild(dev[i]); } //必須先刪除舊節(jié)點后再修改需要改的節(jié)點,否則文本節(jié)點會被刪掉 onLoadedFont(); });
到這里,整個功能就完成了。
總結(jié)總結(jié)一下,這個方案可以讓字體文件沒有加載完的時候,先用一個接近的安全字體讓文本先顯示出來,待字體加載完后再換字體,核心的點是監(jiān)聽字體文件的加載,因為MDN上提供的document.font是一個實驗性功能,兼容性不是很好,所以這里用了投機取巧的辦法去監(jiān)聽window.load,可能會被其他大文件阻塞,也會拖慢監(jiān)聽window.load的其他函數(shù),所以在項目中還是要取舍,沒有完美的方案,只有最合適的方案。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106210.html
摘要:火狐推遲對字體的支持,重點放在格式上。網(wǎng)絡(luò)字體的效率字體文件的體積可能非常的大尤其是對于漢字,而且需要額外的連接,這些都會降低網(wǎng)站頁面的加載速度。 最近興致上來,就想更換了那Blog標題字體(漢字的);網(wǎng)上搜索了一番,發(fā)現(xiàn)蘇新詩柳繁體這款甚合我心;然后就著手搞將了起來,分分鐘也算是替換了;但,這僅僅是此次折騰的開始;這就細細道來作為學(xué)習(xí)筆記記載。 原文首發(fā)鏈接http://www.je...
摘要:火狐推遲對字體的支持,重點放在格式上。網(wǎng)絡(luò)字體的效率字體文件的體積可能非常的大尤其是對于漢字,而且需要額外的連接,這些都會降低網(wǎng)站頁面的加載速度。 最近興致上來,就想更換了那Blog標題字體(漢字的);網(wǎng)上搜索了一番,發(fā)現(xiàn)蘇新詩柳繁體這款甚合我心;然后就著手搞將了起來,分分鐘也算是替換了;但,這僅僅是此次折騰的開始;這就細細道來作為學(xué)習(xí)筆記記載。 原文首發(fā)鏈接http://www.je...
摘要:簡言之,我們認為好的用戶體驗從快速的內(nèi)容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設(shè)計美感的同時,最小化對性能的影響。字型子集設(shè)定到目前為止,子集設(shè)定是改善網(wǎng)頁字體性能最快的方式。 作者 Declan 原文鏈接 最近更新了我們的網(wǎng)站,它是經(jīng)過了設(shè)計上的全面驗收的。但實際上,作為軟件開發(fā)者,我們會注重很多技術(shù)相關(guān)的零碎的東西。我們的目標是控制性能,注重性...
摘要:簡言之,我們認為好的用戶體驗從快速的內(nèi)容傳輸開始,也就意味著性能美觀。每一步我們都在探討如何在獲得好的用戶體驗和保證設(shè)計美感的同時,最小化對性能的影響。字型子集設(shè)定到目前為止,子集設(shè)定是改善網(wǎng)頁字體性能最快的方式。 作者 Declan 原文鏈接 最近更新了我們的網(wǎng)站,它是經(jīng)過了設(shè)計上的全面驗收的。但實際上,作為軟件開發(fā)者,我們會注重很多技術(shù)相關(guān)的零碎的東西。我們的目標是控制性能,注重性...
閱讀 2490·2023-04-25 19:24
閱讀 1710·2021-11-11 16:54
閱讀 2840·2021-11-08 13:19
閱讀 3554·2021-10-25 09:45
閱讀 2561·2021-09-13 10:24
閱讀 3290·2021-09-07 10:15
閱讀 4038·2021-09-07 10:14
閱讀 2959·2019-08-30 15:56