Chrome 79 - 遲到 6 年的 rem/em 修正

閱讀時間約 14 分鐘
眼看 Chrome 79 大概再兩周就要釋出啦!
對大多數人來說,這個也就是 Chrome 例行更新的一個版本。
而對我,Chrome 79 修正了一個最近一年多在我心裡佔有一席之地的 bug,我曾經努力試著解決它,最後似乎也找到自己應對它的方法。而現在它要被修掉了,多少有點感觸 😥。
本文特別想趕在 Chrome 79 正式釋出之前寫出來,讓在閱讀的你也可以一同經歷這個變化的過程。
想直接看結論也可以往下到 TL;DR 的部分喔!

Chrome 的「最小字體」傳說

我想小有接觸前端的人大概都知道 Chrome 有個 最小字體是 12px 的傳說,然而時過境遷、滄海桑田,2019 的現在還是如此嗎?
實際上現在再去 Google “chrome minimum font size” 得到的結果跟討論大都是 2013 年以前的內容,就算有稍微近期的文章,也大都是參考早期文章寫出來的。
從搜尋結果裡面可以找到這個 issue:
裡面提到幾件重要的事情:
  • Chrome 預設的最小字體是和 UI 使用的語言有關的
  • 大部分的 UI 語言預設最小字體是 1px
  • 複雜 UI 語言(多為亞洲語言)的預設最小字體是 10px/12px
  • 2010年時還沒有辦法從設定該改最小字體的設定
而到了 2019 的現在,最小字體已經可以從設定裡面更改了,位置就在「設定」->「自訂字型」
可能很多人會是在看到這篇文章之後才第一次打開這個設定畫面,比對一下上面列出來的項目可以發現繁中 UI 的 Chrome 的最小字體預設值就是 12px。
我猜如果從安裝時就是英文版 UI,預設值應該會是 0px/6px。
曾經是傳說的最小字體 12px,僅限於某些 UI 語言(基本上就是中文、日文、韓文、泰文)的瀏覽器。
現在其實是使用者把它調低就可以解決的問題。當然,對於開發者來說還是一個無法跨越的障礙。
做一個 fiddle 來測試一下「沒調設定」跟「調過設定」的結果: https://jsfiddle.net/pc035860/jgtfdL98/4/

Twitch 聽說你是 rem 排版大師?

自從近年各瀏覽器對 rem 的支援度有提高之後,坊間出現一些使用 rem 為單位進行網頁排版的文章,並且漸漸也有些網站開始使用這種排版方法(雖然我覺得還是相對蠻少的)。
建議往下看之前要先瞭解一下用 rem 單位進行排版大概是怎麼樣進行,可以參考下面這篇 sitepoint 的文章 https://www.sitepoint.com/understanding-and-using-rem-units-in-css/
普遍常見的起手式,是把 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 起跳。
類似問題,其實也曾經在 Apple 的網站上出現過,不過當時是用 em 為單位。
眼尖的你可能會在上面的截圖中發現,字體大小是相同的。那麼我們就接著來看字體大小的部分:
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 來做計算
這邊我做了一個簡單的驗證用 fiddle: https://jsfiddle.net/pc035860/athfj0dc/18/
裡面的 .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
雖然會失去瀏覽器設定「字型大小」的彈性,但不失為一個解決辦法。
用這個更新的 fiddle 來測試: https://jsfiddle.net/pc035860/athfj0dc/20/
其實避免碰到上面這種 rem 單位排版問題的方法就是總是將 base 設為 12px 以上。雖然會造成使用時換算單位的麻煩,但總比碰到這種難以 debug 的問題來的好。
同場加映一個也碰到類似問題的網站 issue: https://github.com/squidfunk/mkdocs-material/issues/911

擴充功能: Twitch REM fix

於是我為了我往後美好的瀏覽 Twitch 體驗,我決定做將這個 workaround 做成 Chrome extension。
起初還有「要判斷當前 UI 語言之後再來套用」之類的天真(?)想法,靜下心來仔細想想,沒有問題的人根本不會來裝這個extension
釋懷後的我,緩緩地開了個新的 CSS 檔案,在裡面輸入:
contentscript.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 。
這次在旁邊加了使用同樣 rem 做為長寬的 div 來對照: https://jsfiddle.net/pc035860/jgtfdL98/35/
分別對 繁中 / 英文 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 應該是出於好意啦… 嗯…
最後把這個隱藏門檻也考慮進去,整理進前面提到的式子:
即將進入廣告,捲動後可繼續閱讀
為什麼會看到廣告
4會員
7內容數
網頁前端是一個需要與時俱進的工作。 你也喜歡前端嗎? 在這邊你可以找到一些前端小知識、新技術或是趣聞,歡迎與我們一同成長 🚀
留言0
查看全部
發表第一個留言支持創作者!
批歪的沙龍 的其他內容
隨著「復仇者聯盟:終局之戰」的上映,Google 在和薩諾斯與無限手套相關的搜尋結果頁面加了一個灰飛煙滅的特效。 特效被發現後引起了各界熱烈的討論,所以這週末的長知識就來蹭個熱度,看一下灰飛煙滅的特效是如何完成的。
隨著「復仇者聯盟:終局之戰」的上映,Google 在和薩諾斯與無限手套相關的搜尋結果頁面加了一個灰飛煙滅的特效。 特效被發現後引起了各界熱烈的討論,所以這週末的長知識就來蹭個熱度,看一下灰飛煙滅的特效是如何完成的。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
Google 將會在 Chrome 92 加入名為 Back-Forward Cache (返往快取) 功能,不過這個功能其實已經在 Android 版的 Chrome 87 上推出,評價還非常不錯,今次 Google 就正式把這個功能擴展至桌面版。
Thumbnail
每周一篇文章的讀書會心得報告摘要與筆記,本次分享文章為:用Chrome還是Safari,洩露你的工作心態?經濟學家:選擇揭露了你的特質。 1.該如何預測一個人會做這份工作多久,以及表現如何? 2.線上職業評量預期與實際之間的落差 3.瀏覽器背後代表的心態差異 4.一套最好的話術,通常會漏失彈性的好處
Thumbnail
Chrome 擴充功能推薦:快速複製APA文獻引用格式、網頁螢光劃記重點、查詢網頁英文單字中譯、封鎖特定網站、白噪音番茄鐘、YouTube同時瀏覽影片與留言、英打錯字文法糾錯。
Thumbnail
大多數人都依賴Google Chrome作為其主要瀏覽器,儘管對於普通人來說這不會引起太大爭議,但我們以技術為重的個人可能會對使用Google Chrome作為我們的主要互聯網訪問來源感到有些疑惑。。。
轉移自 LogDown 原文日期 March 12, 2015 20:26  前陣子看到別人的 Chrome Extension 之後,筆者也開始好奇這塊領域。 官方引導全都是英文,但不會太難看懂。 簡言之只要為應用準備好一個資料夾,然後裡面有以下四個檔案即可。 manifest.js
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
Google 將會在 Chrome 92 加入名為 Back-Forward Cache (返往快取) 功能,不過這個功能其實已經在 Android 版的 Chrome 87 上推出,評價還非常不錯,今次 Google 就正式把這個功能擴展至桌面版。
Thumbnail
每周一篇文章的讀書會心得報告摘要與筆記,本次分享文章為:用Chrome還是Safari,洩露你的工作心態?經濟學家:選擇揭露了你的特質。 1.該如何預測一個人會做這份工作多久,以及表現如何? 2.線上職業評量預期與實際之間的落差 3.瀏覽器背後代表的心態差異 4.一套最好的話術,通常會漏失彈性的好處
Thumbnail
Chrome 擴充功能推薦:快速複製APA文獻引用格式、網頁螢光劃記重點、查詢網頁英文單字中譯、封鎖特定網站、白噪音番茄鐘、YouTube同時瀏覽影片與留言、英打錯字文法糾錯。
Thumbnail
大多數人都依賴Google Chrome作為其主要瀏覽器,儘管對於普通人來說這不會引起太大爭議,但我們以技術為重的個人可能會對使用Google Chrome作為我們的主要互聯網訪問來源感到有些疑惑。。。
轉移自 LogDown 原文日期 March 12, 2015 20:26  前陣子看到別人的 Chrome Extension 之後,筆者也開始好奇這塊領域。 官方引導全都是英文,但不會太難看懂。 簡言之只要為應用準備好一個資料夾,然後裡面有以下四個檔案即可。 manifest.js