解決 “頁面中文字增多,字號突然變大” 的問題

桔子_Lynn發表於2017-02-28

在之前一篇文章中,曾記錄過一個開發中遇到的問題,在頁面中文字增加到一定數量,或者文字大小設定為某一個值時,頁面中的文字字號會突然變大,超出自己設定的字號大小。

如下圖所示:

 

雖然我設定的字號大小是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: 瀏覽器中手動指定的縮放比例,預設為 1
    • systemFontScale: 系統字型大小,Android裝置可以在「裝置 - 顯示 - 字型大小」處設定,預設為 1
    • clusterWidth: 應用 Font Boosting 特性字型所在元素的寬度(如何確定這個元素請參考上邊兩個連結)
    • screenWidth: 裝置螢幕解析度(DIPs, Density-Independent Pixels),如 iPhone 5 為 320

問題終於得到解決啦,多謝高人指點,比心!

文章參考連結:https://github.com/amfe/article/issues/10

 

相關文章