最近在做一個(gè)手機(jī)端頁面時(shí),遇到了一個(gè)奇怪的問題:字體的顯示大小,與在CSS中指定的大小不一致。大家可以查看這個(gè) Demo (記得打開Chrome DevTools)。 就如上圖所示,你可以發(fā)現(xiàn),原本指定的字體大小是24px,但是最終計(jì)算出來的卻是53px,看到這詭異的結(jié)果,我心中暗罵一句:這什么鬼! 隨后開始對問題各種排查:某個(gè)標(biāo)簽引起的?某個(gè)CSS引起的?又或者是某句JS代碼引起的。通過一坨坨的刪代碼,發(fā)現(xiàn)貌似都不是。我不禁又罵,到底什么鬼!不過中間還是發(fā)現(xiàn)了一些端倪:當(dāng)頁面中的標(biāo)簽數(shù)量或者文本數(shù)量大于某一個(gè)值,或者當(dāng)CSS定義的字體大小落在某個(gè)區(qū)間時(shí),這個(gè)問題才會被觸發(fā)。而且字體變大后的值也隨著原始定義的字體大小而改變。 然后自然就是各種搜索,終于有了新的發(fā)現(xiàn)。原來這個(gè)特性被稱做「Text Autosizer」,又稱「Font Boosting」、「Font Inflation」,是 Webkit 給移動(dòng)端瀏覽器提供的一個(gè)特性:當(dāng)我們在手機(jī)上瀏覽網(wǎng)頁時(shí),很可能因?yàn)樵柬撁鎸挾容^大,在手機(jī)屏幕上縮小后就看不清其中的文字了。而 Font Boosting 特性在這時(shí)會自動(dòng)將其中的文字字體變大,保證在即不需要左右滑動(dòng)屏幕,也不需要雙擊放大屏幕內(nèi)容的前提下,也可以讓人們方便的閱讀頁面中的文本。 不過這個(gè)特性并不總是有必要的,還好在查到問題原因的同時(shí),大家也討論了對這個(gè)問題的一些處理方案:
到這里,我們已經(jīng)明白問題所在,并且也有解決方案了。但是有一個(gè)問題仍然困擾著我:當(dāng)字體大于某一個(gè)值時(shí)(比如當(dāng)不指定viewport width,手機(jī)屏幕width=320,字體大于等于82px時(shí)),這個(gè) Font Boosting 就始終不會被觸發(fā)。Chrome 是如何計(jì)算的,這其中的邏輯又是什么? 這一次問題解決起來就沒有那么容易了,我先是各種搜索無果,然后自己人肉去試,慢慢找規(guī)律,但是發(fā)現(xiàn)變化不是線性的,看來這個(gè)公式還比較復(fù)雜。終于在今天被我發(fā)現(xiàn)了這篇文章: Chromium's Text Autosizer ,徹底解釋了我的疑問。 Font Boosting 具體的實(shí)現(xiàn)代碼在 TextAutosizer.cpp 這個(gè)文件中可以看到,有興趣的可以翻一下。 簡單說來,F(xiàn)ont Boosting 的計(jì)算規(guī)則偽代碼如下: multiplier = Math.max(1, deviceScaleAdjustment * textScalingSlider * systemFontScale * clusterWidth / screenWidth); if (originFontSize < 16) { computedFontSize = originFontSize * multiplier; } else if (16 <= originFontSize <= (32 * multiplier - 16)) { computedFontSize = (originFontSize / 2) + (16 * multiplier - 8); } else if (originFontSize > (32 * multiplier - 16)) { computedFontSize = originFontSize; } 其中變量名解釋如下,更具體的說明可以參考上邊的兩個(gè)鏈接。
說了這么多,貌似只需要記住 Update 2015-7-24: @yisibl 姐姐說,用 Ref.
|
|