在之前一篇文章中,曾記錄過一個開發中遇到的問題,在頁面中文字增加到一定數量,或者文字大小設定為某一個值時,頁面中的文字字號會突然變大,超出自己設定的字號大小。
如下圖所示:
雖然我設定的字號大小是24px,但是在computed下卻是28.7px,超出我所設定的大小,那麼問題來源是什麼?
經高人指點後,該問題終於得到了解決,主要問題在於 Font Boosting 特性。
這個特性被稱做「Text Autosizer」,又稱「Font Boosting」、「Font Inflation」,是 Webkit 給移動端瀏覽器提供的一個特性:當我們在手機上瀏覽網頁時,
很可能因為原始頁面寬度較大,在手機螢幕上縮小後就看不清其中的文字了。而 Font Boosting 特性在這時會自動將其中的文字字型變大,保證在既不需要左右滑動螢幕,
也不需要雙擊放大螢幕內容的前提下,也可以讓人們方便的閱讀頁面中的文字。
下面給出幾個解決方案:
1. 手動指定 viewport width=320
,這時 Font Boosting 不會被觸發。(後邊可以知道,這個說法不嚴謹,在其他設定均為預設值時,這一條才有效)
2. Font Boosting 僅在未限定尺寸的文字流中有效,給元素指定寬高,就可以避免 Font Boosting 被觸發。這也就解釋了為什麼我在給元素設定高度以後,該問題便解決了。
3. 顯然第 2 條方案是有缺陷的,文字內容不可能都指定寬高。不過可以通過指定 max-height
來解決。比如 body * { max-height: 999999px; }
就可以無副作用的禁掉 Font Boosting 特性。
當然,我覺得沒必要使用通用選擇器,用類似 p { max-height: 999999px; }
可能更好一些。
那麼瀏覽器是怎麼計算字號並控制其大小的呢,下面是瀏覽器的計算邏輯:
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;
}
變數名解釋如下:
originFontSize
: 原始字型大小computedFontSize
: 經過計算後的字型大小multiplier
: 換算係數,值由以下幾個值計算得到deviceScaleAdjustment
: 當指定viewport width=device-width
時此值為 1,否則值在 1.05 - 1.3 之間,有專門的計算規則textScalingSlider
: 瀏覽器中手動指定的縮放比例,預設為 1systemFontScale
: 系統字型大小,Android裝置可以在「裝置 - 顯示 - 字型大小」處設定,預設為 1clusterWidth
: 應用 Font Boosting 特性字型所在元素的寬度(如何確定這個元素請參考上邊兩個連結)screenWidth
: 裝置螢幕解析度(DIPs, Density-Independent Pixels),如 iPhone 5 為 320
問題終於得到解決啦,多謝高人指點,比心!
文章參考連結:https://github.com/amfe/article/issues/10