最近在做一個(gè)手機(jī)端頁面時(shí),遇到了一個(gè)奇怪的問題:字體的顯示大小,與在CSS中指定的大小不一致。大家可以查看這個(gè) Demo (記得打開Chrome DevTools)。
就如上圖所示,你可以發(fā)現(xiàn),原本指定的字體大小是24px,但是最終計(jì)算出來的卻是53px,看到這詭異的結(jié)果,我心中暗罵一句:這什么鬼!
隨后開始對(duì)問題各種排查:某個(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è)問題才會(huì)被觸發(fā)。而且字體變大后的值也隨著原始定義的字體大小而改變。
然后自然就是各種搜索,終于有了新的發(fā)現(xiàn)。原來這個(gè)特性被稱做「Text Autosizer」,又稱「Font Boosting」、「Font Inflation」,是 Webkit 給移動(dòng)端瀏覽器提供的一個(gè)特性:當(dāng)我們?cè)谑謾C(jī)上瀏覽網(wǎng)頁時(shí),很可能因?yàn)樵柬撁鎸挾容^大,在手機(jī)屏幕上縮小后就看不清其中的文字了。而 Font Boosting 特性在這時(shí)會(huì)自動(dòng)將其中的文字字體變大,保證在即不需要左右滑動(dòng)屏幕,也不需要雙擊放大屏幕內(nèi)容的前提下,也可以讓人們方便的閱讀頁面中的文本。
不過這個(gè)特性并不總是有必要的,還好在查到問題原因的同時(shí),大家也討論了對(duì)這個(gè)問題的一些處理方案:
viewport width=320
,這時(shí) Font Boosting 不會(huì)被觸發(fā)。(后邊可以知道,這個(gè)說法不嚴(yán)謹(jǐn),在其他設(shè)置均為默認(rèn)值時(shí),這一條才有效) max-height
min-height
, min-width
, max-width
max-height
有效) 也是可以的。比如 body * { max-height: 999999px; }
就可以無副作用的禁掉 Font Boosting 特性。當(dāng)然,我覺得沒必要使用通用選擇器,用類似 p { max-height: 999999px; }
可能更好一些。 到這里,我們已經(jīng)明白問題所在,并且也有解決方案了。但是有一個(gè)問題仍然困擾著我:當(dāng)字體大于某一個(gè)值時(shí)(比如當(dāng)不指定viewport width,手機(jī)屏幕width=320,字體大于等于82px時(shí)),這個(gè) Font Boosting 就始終不會(huì)被觸發(fā)。Chrome 是如何計(jì)算的,這其中的邏輯又是什么?
這一次問題解決起來就沒有那么容易了,我先是各種搜索無果,然后自己人肉去試,慢慢找規(guī)律,但是發(fā)現(xiàn)變化不是線性的,看來這個(gè)公式還比較復(fù)雜。終于在今天被我發(fā)現(xiàn)了這篇文章: Chromium's Text Autosizer ,徹底解釋了我的疑問。
Font Boosting 具體的實(shí)現(xiàn)代碼在 TextAutosizer.cpp 這個(gè)文件中可以看到,有興趣的可以翻一下。
簡(jiǎn)單說來,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è)鏈接。
originFontSize
: 原始字體大小 computedFontSize
: 經(jīng)過計(jì)算后的字體大小 multiplier
: 換算系數(shù),值由以下幾個(gè)值計(jì)算得到 deviceScaleAdjustment
: 當(dāng)指定 viewport width=device-width
時(shí)此值為 1,否則值在 1.05 - 1.3 之間,有專門的計(jì)算規(guī)則 textScalingSlider
: 瀏覽器中手動(dòng)指定的縮放比例,默認(rèn)為 1 systemFontScale
: 系統(tǒng)字體大小,Android設(shè)備可以在「設(shè)備 - 顯示 - 字體大小」處設(shè)置,默認(rèn)為 1 clusterWidth
: 應(yīng)用 Font Boosting 特性字體所在元素的寬度(如何確定這個(gè)元素請(qǐng)參考上邊兩個(gè)鏈接) screenWidth
: 設(shè)備屏幕分辨率(DIPs, Density-Independent Pixels),如 iPhone 5 為 320 說了這么多,貌似只需要記住 p { max-height: 999999px; }
就OK了。。。-_-!!!
Update 2015-7-24:
@yisibl 姐姐說,用 max-height: 100%
可能會(huì)更好一些。
Ref.
聯(lián)系客服