被放大的字体

2018-06-17 jude 更多博文 » 博客 » GitHub »

原文链接 http://judes.me/frontend/2018/06/17/font-boosting.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


前几天踩到一个坑,弹窗里的文字稍微多了一点,字体就会变大:

文字少的表现文字少的表现

文字多的表现文字多的表现

可以看到第二张图中的文字只比第一段的多一个 "abcd" ,但字体明显不一样大。查看具体的 style 值,发现就算是应用了同样的 0.6222rem ,算出来的值都不一样:

文字少的 fontSize文字少的 fontSize

文字多的 fontSize文字多的 fontSize

这么诡异的问题,应该不止我一个遇到!很快我就从网上搜到事情的真相。如果你英文较好,有耐心,又有梯子的话,可以直接看原文:Chromium’s Text Autosizer

原来这个自动放大文字的特性名字叫做 font bosting 或者 font inflation,只在移动端的浏览器上出现,旨在提升那些按 PC 端大小展示的页面的文字的可读性。

禁用 font boosting 的方法

有时候这个特性不是你想要的,禁用方法要从原理中找。

官方表明这个特性不会应用在下面的元素中:

  • 显式声明高度的区块(因为在这时增大字体有可能会超出区块)
  • 表单的控制元素(form controls: text fields, buttons, checkboxes, range controls, or color pickers, etc.)
  • 排成多排(列)的超链接(navigation headers)
  • 带上 white-space: nowrap 样式的区块
  • 只包含少量文字的簇(clusters, 可以理解为结构层次相似的几个区块。所有元素都会被划分到特定的簇当中,每个簇都有特定的字体放大比率)

从第一条可以知道,可以显式声明区块的高度或者最大高度,比如 max-height: 9999px; 来禁用特性。

而簇的放大比率有以下计算公式:

clusterMultiplier = max(1, textScalingSlider × systemFontScale × clusterWidth ∕ screenWidth)

由这个公式可以推导出,如果这样设置头部 meta 标签:

<meta name="viewport" content="width=device-width">

可以令 font boosting 失效。因为 textScalingSlider 和 systemFontScale 默认为 1 ,而 clusterWidth <= viewport width == screenWidth ,clusterMultiplier 就等于 1 。

以上两种方法都难以满足实际情况时,还可以设置 text-size-adjust: none; 样式禁用特性。不过这个样式比较新,浏览器还没有全面支持,可以用上特性检测结合第一种方法使用:

.disableFontBoosting {
  max-height: 9999px;
}
@supports(text-size-adjust: none){
  .disableFontBoosting {
    max-height: none;
    text-size-adjust: none;
  }
}

参考