在我們的頁面中,經常會出現這樣的問題,一塊區域內的文本或者邊框,在展示的時候,變得特別的模糊,如下(數據經過脫敏處理):
正常而言,應該是這樣的:
emmm,可能大圖不是很明顯,我們取一細節對比,就非常直觀了:
何時觸發這種現象?
那么?什么時候會觸發這種問題呢?在 Google 上,其實我們能搜到非常多類似的案例,總結而言:
- 當文本元素的某個祖先容器存在
transform: translate()
或者transform: scale()
等transform
操作時,容易出現這種問題
當然,這只是必要條件,不是充分條件。繼續深入探究,會發現,必須還得同時滿足一些其它條件:
- 元素作用了
transform: translate()
或者transform: scale()
后的計算值產生了非整數
譬如,上述案例觸發的 CSS 代碼如下:
.container {
position: absolute;
width: 1104px;
height: 475px;
top: 50%;
transform: translateY(-50%);
// ...
}
由於元素的高度為 475px
,translateY(-50%)
等於 237.5px
,非整數,才導致了內部的字體模糊。
但是,需要注意的是,並非所有產生的非整數都會導致了內部的字體模糊。
這里有個簡單的示意:
還是上述的例子,當高度從 477px
一直調整到 469px
的過程中,只有 477px
和 475px
導致了模糊,而 473, 471, 469
則沒有。所以,這也只是引發模糊的一個必要條件。
- 文本內容是否模糊還與屏幕有關,高清屏(dpr > 2)下不容易觸發,更多發生在普通屏幕下(dpr = 1)
在我實測的過程中還發現,這個現象基本只會發生在 dpr 為 1 的普通屏幕下。
類似於 MAC 的高清屏幕則不太會觸發這個問題。
dpr = 物理像素 / 設備獨立像素,表示設備像素比。這個與我們通常說的視網膜屏(多倍屏,Retina屏)有關。設備像素比描述的是未縮放狀態下,物理像素和設備獨立像素的初始比例關系。
- 並非所有瀏覽器都是這個表現,基本發生在 chromium 內核。
為何發生這種現象呢?
那么,為何會發生這種現象?針對這個問題,沒有找到特別官方的回答,普遍的認為是因為:
由於瀏覽器將圖層拆分到 GPU 以進行 3D 轉換,而非整數的像素偏移,使得 Chrome 在字體渲染的時候,不是那么的精確。
關於這個問題,感興趣的可以再看看這兩個討論:
- Chromium Bugs -- Issue 521364: Transformed text at fractional offsets is very blurry.
- Serious bug: Slick Slider turns off subpixel font rendering on the entire site in Chrome #2275
如何解決?
那么針對這個問題,我們該如何解決呢?社區里給出的一種方案:
- 給元素設置
-webkit-font-smoothing: antialiased
font-smooth
CSS 屬性用來控制字體渲染時的平滑效果,該特性是非標准的,我們應該盡量不要在生產環境中使用它。並且在我的實測中,這個方法不太奏效。
- 保證運用了
transform: translate()
或者transform: scale()
的元素的高寬為偶數
如果你賦予給元素的 transform
的值非常明確,譬如我上文例子中的利用其來對元素進行水平垂直居中 -- transform: translate(-50%, -50%)
,讓元素的高寬為偶數這個方法是可行的,但如果當你無法確定transform
的值,譬如 transform: translateX(-31.24%)
或者是 transform: scale(1.05)`,那這個方法依舊無法奏效。
- 棄用
transform
如果這個問題對你的頁面非常致命,那么只能棄用 transform
,尋找替代方案。大部分的時候,我們還是可以找到不使用 transform
的替代方案的。
總結一下,本文簡單探究了在 Chromium 內核下,使用了 transform
導致內部文本模糊的現象,並且給出了一些可嘗試的解決方案,實際遇到,需要多加調試,嘗試最優的解決方案。
最后
好了,本文到此結束,希望本文對你有所幫助 😃
更多精彩 CSS 技術文章匯總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
如果還有什么疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。