眼看 Chrome 79 大概再兩周就要釋出啦!
對大多數人來說,這個也就是 Chrome 例行更新的一個版本。
而對我,Chrome 79 修正了一個最近一年多在我心裡佔有一席之地的 bug,我曾經努力試著解決它,最後似乎也找到自己應對它的方法。而現在它要被修掉了,多少有點感觸 😥。
本文特別想趕在 Chrome 79 正式釋出之前寫出來,讓在閱讀的你也可以一同經歷這個變化的過程。
想直接看結論也可以往下到 TL;DR 的部分喔!
Chrome 的「最小字體」傳說
我想小有接觸前端的人大概都知道 Chrome 有個 最小字體是 12px 的傳說,然而時過境遷、滄海桑田,2019 的現在還是如此嗎?
從搜尋結果裡面可以找到這個 issue:
裡面提到幾件重要的事情:
- Chrome 預設的最小字體是和 UI 使用的語言有關的
- 大部分的 UI 語言預設最小字體是 1px
- 複雜 UI 語言(多為亞洲語言)的預設最小字體是 10px/12px
- 2010年時還沒有辦法從設定該改最小字體的設定
而到了 2019 的現在,最小字體已經可以從設定裡面更改了,位置就在「設定」->「自訂字型」。
可能很多人會是在看到這篇文章之後才第一次打開這個設定畫面,比對一下上面列出來的項目可以發現繁中 UI 的 Chrome 的最小字體預設值就是 12px。
我猜如果從安裝時就是英文版 UI,預設值應該會是 0px/6px。
曾經是傳說的最小字體 12px,僅限於某些 UI 語言(基本上就是中文、日文、韓文、泰文)的瀏覽器。
現在其實是使用者把它調低就可以解決的問題。當然,對於開發者來說還是一個無法跨越的障礙。
Twitch 聽說你是 rem 排版大師?
自從近年各瀏覽器對 rem 的支援度有提高之後,坊間出現一些使用 rem 為單位進行網頁排版的文章,並且漸漸也有些網站開始使用這種排版方法(雖然我覺得還是相對蠻少的)。
普遍常見的起手式,是把 rem base 設為 1px 或 10px,這樣一來直接使用 rem 單位換算的過程會簡單很多。
其中又以在 <html> 上用 font-size: 62.5% 來設定為 10px 最常見:
Twitch 的大改版衝擊
Twitch 在 2018 年 2 月左右做了一次重大改版,把原本用的
Ember.js 換成 React,這一次改版同時也把網站的排版單位改為 rem,而這也是我們繁中 Chrome 使用者的噩夢開端(好像講得有點誇張了)。
改版之後,原本頻道的資訊頁面變得非常奇怪。下面示範截圖是目前最新版,當然也還是用 rem 單位排版。
正常來說應該是這樣:
改版後就直接跑掉:
這還只是第一眼就覺得不對勁的部分。
用 Firefox 打開 Twitch 來比較就可以看出整個網站都有點不一樣,Chrome 整體似乎大了一號,這邊就單取側邊欄來對比:
WTF!? 不是, Twitch 難道沒有測過嗎…
怎麼一回事
來看一下 Twitch 的 <html> 怎麼寫的
也就是他們的 rem base 是設定為 10px,接著看看對應的 side-nav class 寬度是多少呢?
10 * 24 = 240,他們希望的寬度是 240px,那麼實際上在我們繁中 Chrome 顯示會是多寬呢?
288 / 24 = 12,結果不言而喻啦!
Chrome 的最小字體被套用在 <html> 上,導致 rem 的 base 直接用 12px 起跳。
眼尖的你可能會在上面的截圖中發現,字體大小是相同的。那麼我們就接著來看字體大小的部分:
14 / 1.4 = 10 剛好是設定的 rem base 10px,也就是說 font-size 部分並沒有受到 <html> 上 12px 的影響,依然故我的使用了 10px 來計算。接著我順便檢查了 padding, margin 之類的屬性,發現結果跟上面 width 一樣是用 12px 來計算的,看來只有使用在 font-size 時候的計算是分開的。
於是我們稍微修改一下上面論述,得到一個小結論:
Chrome 的最小字體被套用在 <html> 上,導致 rem 單位使用在 font-size 以外的屬性上時,其 base 直接用 12px 來做計算
裡面的 .box ,希望透過 rem 設定出的正確數值如下:
後面也還會用到這些數值來做正確性的驗證,稍微有個印象就好了。
好啦,都是 Chrome 的錯
前面說過現在最小字體可以調整是吧,那我們把最小字體的設定調到 10px 以下不就好了嗎?
那我們就拿上面驗證用的 fiddle 來比較一下,「保持預設 12px」跟「調整到 0px」的結果:
怎…怎麼這樣,竟然沒有變!?
UI 語言的陷阱
冷靜想想,Twitch 團隊在改版過了一年多的現在都沒有修正是什麼原因?
- 無法 reproduce 問題
- 只有少部分的人有問題,不用管他們
難道問題出在語言上? 讓我們把 Chrome UI 語言設定成英文試試看。
藍框處顯示目前是中文,點擊紅框處可以切換為英文。(註: Mac 使用者需要從「系統偏好設定」->「地區與語言」裡面改)
接著再用上面的 fiddle 來測一次最小字體 0px:
沒錯,把 UI 切成英文後就一切正常了。
順帶一提,初始安裝英文 UI Chrome 的最小字體應該是 0px/6px 其中一個,可以直接得到上圖的結果。因此如果系統語言不是上述亞洲語系的話,壓根就沒有機會看到這個 bug。
總之雖然原因不明,但看起來在繁中 UI 的 Chrome 下,就算已經調整過最小字體,在 <html> 上用 font-size: 62.5% 並沒有辦法把字體壓到 12px 以下。
繁中 UI 的最後一搏
看到這裡是不是你也覺得繁中 UI 的 Chrome 使用者真是太絕望了…
在我多番嘗試之後發現,剩下最後一手可以解決這個問題:
<html> 上指定 rem base 的方式直接寫成 font-size: 10px。
雖然會失去瀏覽器設定「字型大小」的彈性,但不失為一個解決辦法。
其實避免碰到上面這種 rem 單位排版問題的方法就是總是將 base 設為 12px 以上。雖然會造成使用時換算單位的麻煩,但總比碰到這種難以 debug 的問題來的好。
擴充功能: Twitch REM fix
於是我為了我往後美好的瀏覽 Twitch 體驗,我決定做將這個 workaround 做成 Chrome extension。
起初還有「要判斷當前 UI 語言之後再來套用」之類的天真(?)想法,靜下心來仔細想想,沒有問題的人根本不會來裝這個extension。
釋懷後的我,緩緩地開了個新的 CSS 檔案,在裡面輸入:
大功告成。
截圖跟寫說明花的時間還比打這段 CSS 多…
基本上這個 extension 會在 *.twitch.tv 下面無腦套用 contentscript.css 的內容,有修正版面需求的人可以到下面的 Github 網址逛逛:
所以 Chrome 79 是?
好了,上面說了這麼多,總算可以進入正題啦!
來看這個 2013 年的 Chrome issue
這個 issue 是我在最小字體的相關搜尋中翻到的,主訴是「rem/em 用作單位時,在計算結果前就被套用了最小字體的限制」,怎麼聽起來這麼耳熟?
Use computed font-size for em/rem resolution.
This makes us match how Firefox applies minimum font-size and makes us not break relative length computation when pages use a font-size less than the user’s minimum font-size as a basis for widths, heights, margins, padding, etc.
從中推敲一下,未修正前的版本大概可以這樣表示(純示意,我沒有去翻 source code):
這個 issue 最近終於修正完畢,在 Chrome 79 會 release。
在修正後,resultRelativeLength 的式子大致上變成這樣(純示意,我沒有去翻 source code):
我實際從 beta channel 安裝 Chrome 79 的測試的結果也沒有問題,真的修正啦!
什麼都不用做,只要更新到 Chrome 79 以上、上面的 extension 也不用裝,各種 rem 單位排版造成的問題就迎刃而解。
如果你常在看的網站 (例如: Twitch),突然變了(回原)樣,千萬別太驚訝喔 😉
值得特別提出的是,在 Chrome 79 的繁中 UI 上用 font-size: 62.5% 還是沒有辦法把渲染字體壓到 12px 以下,就算你調了最小字體的設定也一樣。 更多討論請見本文最後的附錄。
TL;DR
🍖 Chrome 的最小字體其實現在可以設定了,並且根據安裝時的 UI 語言,預設值會不同
- 中文、韓文、日文、泰文等 是 10px/12px
- 其他通常是 6px 或以下
🍖 Twitch 改版後使用了 rem 單位排版,在繁中 UI 的 Chrome 看起來會跑掉
🍖 在繁中 UI 的 Chrome 底下,如果 font-size 用百分比單位表示,就算調了最小字體設定也沒有辦法被壓到小於 12px
- 因此造成 Twitch 改版後版面跑掉
- 把 UI 語言調成英文可以解決這個問題
- 用 font-size: 10px 取代 font-size: 62.5% 是一種 workaround
- 我把 workaround 做成 extension 了
🍖 Chrome 79 會修正套用最小字體的方式
- rem 單位排版計算錯誤的問題會消失
- 可能有些你看習慣的網站會有變化 (例如: Twitch)
- 套用在 <html> 上時,繁中 UI 百分比 font-size 的最小值依然是 12px (見附錄)
後記
從去年改版後, Twitch 版面的問題就一直困擾著我,有點像是揮不走的蒼蠅,每次打開網站就看到 😨
直到最近(2019/9)又再一次改版,新的版面搭上崩壞的 rem 單位真的是慘不忍睹,我只好弄了一個 extension 先撐著。
偶然發現下一版 Chrome release (大概兩周後)就可以躺著解決(?),發這篇文正是為了紀念這期間我內心的掙扎,還有製作擴充功能(跟它的說明)的流下的汗水。
我會懷念你的, Chrome 78 (含以前)!
感謝你讀到這邊,下次有有趣的東西要分享的話,我會再回來的。
附錄: 最終負載測試
以下的測試用 Chrome 79 beta 進行,「最小字體」都已經設定為 0 。
分別對 繁中 / 英文 UI 版本 以及 font-size: 10px / font-size: 62.5% 的組合做交叉測試,得到的結果如下:
🍖 rem 數值用在 width, height 上不受 font-size 指定方式的影響
🍖 在使用者可以設定的「最小字體」之外,還有別的隱藏字體大小門檻
- 只在 font-size 用百分比設定時套用
- 根據 UI 語言會有不同的數值
🍺 繁中 UI 是 12px
🍺 英文 UI 是 9px
- 從 rem base 的角度來看,門檻應該是套用在計算完 rem -> px 結果之後,否則理應會影響我們用 rem 表示的寬跟高
比較一下 Firefox Developer Edition 71 的測試結果:
我想 Chrome 應該是出於好意啦… 嗯…
最後把這個隱藏門檻也考慮進去,整理進前面提到的式子: