1. 程式人生 > >Chrome 和 Web Fonts 二三事

Chrome 和 Web Fonts 二三事

文章目錄

提醒:本文最後更新於 1703 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

Chrome 是我的主力瀏覽器,總得來說用著還算順手,但也經常遇上一些讓人很惱火的地方,例如萬惡的滾動條凍結現象監管不力亂象叢生的擴充套件、越來越反人類的新標籤頁等等。今天要說的是 Chrome(嚴格說是 webkit)下另外一個嚴重的問題,與 Web Fonts 有關。

起因

每臺電腦都會安裝多種字型,網頁中可以通過 css 指定頁面文字使用哪種字型。Web Fonts 則讓瀏覽器擁有使用從網際網路下載的新字型渲染文字的本領。截至到當前,全世界 Alexa 排名前 100 萬的網站中,用到 Web Fonts 技術的已經

佔到 39%

本文不會介紹如何使用 Web Fonts,本文要討論的是這樣一種場景:

瀏覽器要渲染使用了 Web 字型的文字,就必須從網際網路下載字型。由於網路的不確定性,如果下載字型花費的時間非常久,瀏覽器該如何處理?

實際上,瀏覽器能使用的策略並不多,無外乎以下幾種:

  1. 先使用系統預設字型渲染文字;等 Web 字型下載完,使用新字型再渲染一次;
  2. 等到 Web 字型下載完成,才渲染文字。也就是字型下載完全阻塞對應文字渲染;
  3. 先跳過文字的渲染;一段時間後,如果 Web 字型仍未下載完,使用系統預設字型渲染文字;等字型下載完,再次渲染;

方案 1 的好處是使用者可以第一時間看到文字內容,壞處是:兩種字型之間的差異,一定會造成內容抖動。早期的 Firefox 以及現階段所有 IE 都是採用的這種方案。

方案 2 的好處是完全避免了內容抖動,壞處也很明顯:字型下載需要多久,使用者就有多久完全看不到文字內容。現階段基於 Webkit 核心的瀏覽器,如 Chrome 和 Safari 都是如此。

方案 3 則是一個折中方案,如果 Web 字型能在一段時間內載入完,不會有因為字型變換帶來的抖動;同時如果載入字型需要很久,也不至於不顯示文字。現階段 Firefox 採用的這種方案。Firefox 預設等 3 秒,可以找到 about:config 中的 gfx.downloadable_fonts.fallback_delay 配置來修改。

實際上,還有人提出第 1、3 兩種方案中,如果字型下載完後只是放入快取,而不是再次渲染,就可以避免內容抖動。但這樣會造成使用者連續兩次訪問同一網頁,可能看到不一樣的文字渲染效果。到目前為止,沒有瀏覽器採用這種方案。

無論是什麼方案,都應該隻影響使用了 Web Fonts 的文字渲染,頁面上其他元素的渲染不應該受到影響,更不應該停止。但是,在 IE 中,如果 Web Fonts 定義之前有任何 JS 程式碼,瀏覽器會停止所有的渲染工作,直到字型下載完成或失敗。另外,IE 還會下載頁面上定義的全部 Web Fonts 檔案,無論是否會被用到。

不知道大家是否遇到過這樣的情況:用 Chrome 訪問部分網站時,經常圖片都載入完了,原始碼也是完整的,就是頁面上一個字都沒有,而 Firefox 沒這個問題。看到這裡,大家應該都明白了:這很有可能是因為字型檔案那個請求遲遲得不到響應造成的。出現這種情況時,點選 Chrome 的停止按鈕,通常文字就能出來。原理很簡單:手動告訴瀏覽器不要傻等 Web Fonts 了,馬上使用預設字型渲染。更徹底的解決方案是換用穩定可靠的網路來訪問這些網站(如:googleusercontent.com)。

轉機

雖然以上描述的問題不能完全怪 Chrome,但 Chrome 的做法確實不太合理。通常,使用 Web Fonts 只是為了給使用者帶來更好的視覺體驗,而讓使用者更快的看到頁面內容才應該是優先考慮的。這種為了更好的效果(以及避免內容抖動)而降低可用性的做法,實際上是在傷害使用者體驗。

下面這個表格,描述了字型大小分佈,以及不同比例使用者載入字型檔案所需時間:

Web 字型大小 佔比 50% 70% 90% 95% 99%
0KB - 10KB 5.47% 136 ms 264 ms 785 ms 1.44 s 5.05 s
10KB - 50KB 77.55% 111 ms 259 ms 892 ms 1.69 s 6.43 s
50KB - 100KB 14.00% 167 ms 882 ms 1.31 s 2.54 s 9.74 s
100KB - 1MB 2.96% 198 ms 534 ms 2.06 s 4.19 s 10+ s
1MB+ 0.02% 370 ms 969 ms 4.22 s 9.21 s 10+ s

可以看到,大部分字型檔案都在 100kb 以下,這時 95% 的使用者都能在 3s 內下載完。同時也可以看到,仍然有一部分使用者需要很久才能下載完字型,這意味著如果他們用的是 Chrome 或 Safari,很長一段時間內他們看到的頁面上很可能沒有任何文字。

幸好 Chrome 的開發人員也意識到了這一點,很早就開始了對這個問題的討論。並且,從 Chrome 35(當前還是 dev 版)開始,Chrome 採用了跟 Firefox 一樣的策略:對於使用了 Web Fonts 的文字,如果三秒後字型還沒載入完,用預設字型渲染;等字型載入完成,使用新字型再次渲染。對照上面的表格,這個策略十分合理,希望 Safari 也能跟進。

尾聲

記得 Web Fonts 這項技術剛出來的時候,大家就討論過中文 Web 字體面臨的難題。相比英文字型幾十 kb 的大小,中文字型少說好幾 M 的身材很容易讓人望而卻步。好在聰明的同學們很快發現,我們可以為頁面上少量需要特別設計的文字定製字型;我們還可以把 Web Fonts 用在實現網站小圖示上。這樣,字型檔案大小可以得到控制。但本文提到的阻塞 Webkit 渲染文字的問題不容忽視,所以有一些建議供大家參考:

  1. 不濫用 Web Fonts(任何新技術都不要濫用!);
  2. 在所有 JS 程式碼之前定義 Web Fonts(否則在 IE 中,字型檔案的載入會阻塞所有介面渲染);
  3. 不要定義不會被用到的 Web Fonts(IE 會載入它們);
  4. 常規的靜態資源優化手段也要用在 Web Fonts 上(快取、GZip 等等);
  5. 對於不同業務用到的相同 Web Fonts,使用同一個地址(類似 JS 公共庫託管,同樣是為了儘可能利用瀏覽器快取),需要特別注意的是:Firefox 下針對非同源字型,需要啟用 CORS(通過 Access-Control-Allow-Origin 響應頭來控制);

--EOF--

提醒:本文最後更新於 1703 天前,文中所描述的資訊可能已發生改變,請謹慎使用。