flexible.js字型大小詭異現象解析及解決方案

來源:互聯網
上載者:User

標籤:

最近在做一個手機端頁面時,遇到了一個奇怪的問題:字型的顯示大小,與在CSS中指定的大小不一致。大家可以查看這個Demo(記得開啟Chrome DevTools)。

就如所示,你可以發現,原本指定的字型大小是24px,但是最終計算出來的卻是53px,看到這詭異的結果,我心中暗罵一句:這什麼鬼!

隨後開始對問題各種排查:某個標籤引起的?某個CSS引起的?又或者是某句JS代碼引起的。通過一坨坨的刪代碼,發現貌似都不是。我不禁又罵,到底什麼鬼!不過中間還是發現了一些端倪:當頁面中的標籤數量或者文本數量大於某一個值,或者當CSS定義的字型大小落在某個區間時,這個問題才會被觸發。而且字型變大後的值也隨著原始定義的字型大小而改變。

然後自然就是各種搜尋,終於有了新的發現。原來這個特性被稱做「Text Autosizer」,又稱「Font Boosting」、「Font Inflation」,是 Webkit 給移動端瀏覽器提供的一個特性:當我們在手機上瀏覽網頁時,很可能因為原始頁面寬度較大,在手機螢幕上縮小後就看不清其中的文字了。而 Font Boosting 特性在這時會自動將其中的文字字型變大,保證在即不需要左右滑動螢幕,也不需要雙擊放大螢幕內容的前提下,也可以讓人們方便的閱讀頁面中的文本。

不過這個特性並不總是有必要的,還好在查到問題原因的同時,大家也討論了對這個問題的一些處理方案:

  1. 手動指定 viewport width=320,這時 Font Boosting 不會被觸發。(後邊可以知道,這個說法不嚴謹,在其他設定均為預設值時,這一條才有效)
  2. Font Boosting 僅在未限定尺寸的文字資料流中有效,給元素指定寬高,就可以避免 Font Boosting 被觸發。
  3. 顯然第 2 條方案是有缺陷的,常值內容不可能都指定寬高。不過還好,我們通過指定 max-height ,min-heightmin-widthmax-width(經 @Ovaldi 指正,只有 max-height 有效) 也是可以的。比如body * { max-height: 999999px; } 就可以無副作用的禁掉 Font Boosting 特性。當然,我覺得沒必要使用通用選取器,用類似 p { max-height: 999999px; } 可能更好一些。

到這裡,我們已經明白問題所在,並且也有解決方案了。但是有一個問題仍然困擾著我:當字型大於某一個值時(比如當不指定viewport width,手機螢幕width=320,字型大於等於82px時),這個 Font Boosting 就始終不會被觸發。Chrome 是如何計算的,這其中的邏輯又是什嗎?

這一次問題解決起來就沒有那麼容易了,我先是各種搜尋無果,然後自己人肉去試,慢慢找規律,但是發現變化不是線性,看來這個公式還比較複雜。終於在今天被我發現了這篇文章:Chromium‘s Text Autosizer,徹底解釋了我的疑問。

Font Boosting 具體的實現代碼在 TextAutosizer.cpp 這個檔案中可以看到,有興趣的可以翻一下。

簡單說來,Font Boosting 的計算規則虛擬碼如下:

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

說了這麼多,貌似只需要記住 p { max-height: 999999px; } 就OK了。。。-_-!!!

用 max-height: 100% 可能會更好一些。

 

WebKit 中應該有判斷如果initial-scale=1時,不觸發Font Boosting。

<meta name="viewport" content="width=device-width, initial-scale=1"><!-- 或 --><meta name ="viewport" content ="initial-scale=1, maximum-scale=1, minimum-scale=1">


flexible.js字型大小詭異現象解析及解決方案

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.