Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font Boosting #10

Open
mingelz opened this issue Aug 18, 2015 · 68 comments
Open

Font Boosting #10

mingelz opened this issue Aug 18, 2015 · 68 comments

Comments

@mingelz
Copy link

mingelz commented Aug 18, 2015

最近在做一个手机端页面时,遇到了一个奇怪的问题:字体的显示大小,与在CSS中指定的大小不一致。大家可以查看这个Demo(记得打开Chrome DevTools)。

Font Boosting Test

就如上图所示,你可以发现,原本指定的字体大小是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-height, min-width, max-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了。。。-_-!!!

Update 2015-7-24:
@yisibl 姐姐说,用 max-height: 100% 可能会更好一些。

Ref.

  1. Webkit Bug 84186 Webkit Bugs 上记录的这个问题,最早从 2012 年 4 月份就开始讨论这个问题了,但好像都没有引起我们的任何关注。
  2. Chromium's Text Autosizer 关于 Font Boosting 最重要的一篇文章,更确切的说是论文。
  3. Font boosting in mobile browsers
  4. Font Boosting 一个俄国人用英文写的文章。
  5. 一堆 StackOverflow 上的问答,用 Font Boosting 搜可以出来一大坨,这里就不列了。
@bsed
Copy link

bsed commented Aug 18, 2015

good!

@banrikun
Copy link

Nice boat!

@yisibl
Copy link

yisibl commented Aug 18, 2015

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">

@ovaldi
Copy link

ovaldi commented Sep 7, 2015

哈哈,今天也刚发现这个问题,在stackoverflow找到的答案http://stackoverflow.com/questions/13416989/computed-font-size-is-bigger-than-defined-in-css-on-the-asus-nexus-7

不过,除了max-height, 貌似min-height、min-width、max-width这几个并不能解决font-boosting的问题啦,楼主确认下?

@mingelz
Copy link
Author

mingelz commented Sep 10, 2015

@ovaldi 确实如此,多谢指正。看来不亲自测一下是不能随便乱写的。

@fish-ball
Copy link

太好了。。这个情况发生的时候我也爆头了。。

@bluest-hu
Copy link

太棒,困恼我好久的问题。

@sweet-zone
Copy link

我第一反应就是看了下meta标签,果然是没有加meta标签。。。 回头看看评论 ,一丝大神已经写了。。。。不过大概width不是devide-width或者initial-scale不是1的时候不正好是需要缩放的么。。。。

@qingying
Copy link

niubility

@stanleyxu2005
Copy link

在meta里面加入devide-width或者initial-scale可以限制缩放的。

@jiraa
Copy link

jiraa commented Dec 9, 2015

马克一下

@Iamlars
Copy link

Iamlars commented Dec 9, 2015

受教育程度超过小学6年!

@geeeeeeeeek
Copy link

感谢分享!Github Wiki在移动端也会autosize,原来是可以避免的。

@ql2005
Copy link

ql2005 commented Dec 11, 2015

我去...终于找到原因了....泪目.....
被这个坑爹的问题折磨了两天了....
24px比32px还大你敢信?...宽度减小字突然变小是什么鬼....
原来都是这坑货捣的鬼..

@mingelz
Copy link
Author

mingelz commented Dec 11, 2015

@riskers 淘宝 flexible 默认是可能触发 foot-boosting 的,我也是在 flexible 环境下发现的这个问题。

@Thinking80s
Copy link

同样也遇到过这个问题,原来是font-boosting。

@FrankFang
Copy link

特地赶来赞一个

@sjclijie
Copy link

我们团队曾经也遇到过这个问题,最后加了一个max-height解决,在stackoverflow找的方案。

@MicleMing
Copy link

泪流满面T-T

@bluest-hu
Copy link

* {
    padding: 0;
    margin: 0;
    max-height: 100000000px;
}

当我这么写的时候一些iPhone在渲染页面时候一场不能识别元素高度 。
比如这个紫色div设置了1090px的高度但是无效。
qq 20160118224255
换成max-height: 999999px;也会在iPhone的QQ浏览器中出问题。

@xushuwei202
Copy link

如果mobile开发中采用淘宝 flexible方案,想解决Font Boosting问题
1,设置max-height: 999999px;
2, 整个页面滚动条采用isroll

@jin5354
Copy link

jin5354 commented Jan 21, 2016

前几天刚遇到,学习了!

@ystarlongzi
Copy link

好顶赞,郁闷了好久,从 sf 过来的

@johanninos
Copy link

thanks

@imcamo
Copy link

imcamo commented Mar 22, 2016

顶,终于解决了

@gaofant101
Copy link

mark

@supidea
Copy link

supidea commented Mar 23, 2016

我也是遇到这个问题。。。用 淘宝的 flexble.js ,出现了字体大小显示不一样 用楼主的方法可以解决

@lin-hun
Copy link

lin-hun commented Nov 28, 2016

@floraluo 怎么解决的 烦请说下,我也遇到了只有在mx的情况下

@wangmiaoduan
Copy link

用淘宝的flexble.js ,刚好碰到这问题 谢楼主咯

@CodeDreamfy
Copy link

我碰到的问题是,设置同样大小的值但是转出来的rem不一样

  height: 76px; 
  line-height: 76px;

qq 20170410143752

@Keystion
Copy link

mark

@gesilaGRY
Copy link

楼主这个比我的效果好,我最近也遇到了,解决方案是给写了font-size的标签写上:display:inline-block或者flex,然后要是不行再加上min-height:1px就好了,但是好麻烦,我的是文字一多了就遇到这个问题了

@bohancen
Copy link

bohancen commented Jun 2, 2017

最近发现一个新的属性,专门解决楼主说的问题
text-size-adjust:auto | none |

@gesilaGRY
Copy link

...我刚好使用了楼上仁兄的,好用

@ovaldi
Copy link

ovaldi commented Jun 3, 2017

@gesilaGRY text-size-adjust目前还在draft阶段,Browser的support情况目前来看还不理想,如下图:
image

所以现阶段感觉还是使用max-height相对好一些,:)

@choudewh
Copy link

6666666666666 感谢

@Saberization
Copy link

mark一下

@gordon8
Copy link

gordon8 commented Sep 15, 2017

Thanks

@zjh65204
Copy link

niubility

@SayGoodBey
Copy link

SayGoodBey commented Dec 12, 2017

mark

1 similar comment
@ILovePing
Copy link

mark

@AllenZeng
Copy link

感谢

@PolluxLee
Copy link

我对.... CSS 的力量一无所知...

@Gavin257
Copy link

6得不行

@jarjune
Copy link

jarjune commented Oct 21, 2018

ios 3x屏问题补充https://www.cnblogs.com/jarjune/p/8916476.html

@pubdreamcc
Copy link

感谢楼主分享的方法,今天碰到了就解决了### ****

@justsilky
Copy link

mark

@ydyoto
Copy link

ydyoto commented Jun 16, 2019

mark!Orz..

@MadaoChen
Copy link

为什么我在安卓微信浏览器试了没有效果。。

@yurenchen000
Copy link

yurenchen000 commented Jan 31, 2022

最近发现一个新的属性,专门解决楼主说的问题 text-size-adjust:auto | none |

我也遇到这个鬼玩意儿了:
 本来在 android opera 里几下搞好就满意的去干别的了, 后来发现 android chrome 表现鬼畜.
明明写的 font-size:12px !important, 在 android chrome (或 pc chrome F12 mobile 模式) 里 被渲染成 30多px.

 从 1~30px 调整 font-size, 字体还不是连续变化的, 中间会突变一下.
// 非常抓狂!!


我用最上面 metamax-height 方案无效.
// 有些后面动态创建的元素 显示不对.


自己摸索的是用这个可以. (android chrome 97)

 body * {
        max-height: 9999px !important; 
        overflow-y: hidden;
}

不过加上 overflow-y 的方式 总感觉解决方案不干净.


上面同学说的 这个 专用的 text-size-adjust 确实好用.
👍 👍 👍

 body * {
        text-size-adjust: none;
}

// 又念头通达了.

这个鬼特性 不知道残害了多少程序员 😿

@bjzhangtao
Copy link

bjzhangtao commented Jan 31, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests