{"action":"created","issue":{"url":"https://api.github.com/repos/amfe/article/issues/10","labels_url":"https://api.github.com/repos/amfe/article/issues/10/labels{/name}","comments_url":"https://api.github.com/repos/amfe/article/issues/10/comments","events_url":"https://api.github.com/repos/amfe/article/issues/10/events","html_url":"https://github.com/amfe/article/issues/10","id":101587173,"number":10,"title":"Font Boosting","user":{"login":"mingelz","id":339891,"avatar_url":"https://avatars.githubusercontent.com/u/339891?v=3","gravatar_id":"","url":"https://api.github.com/users/mingelz","html_url":"https://github.com/mingelz","followers_url":"https://api.github.com/users/mingelz/followers","following_url":"https://api.github.com/users/mingelz/following{/other_user}","gists_url":"https://api.github.com/users/mingelz/gists{/gist_id}","starred_url":"https://api.github.com/users/mingelz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mingelz/subscriptions","organizations_url":"https://api.github.com/users/mingelz/orgs","repos_url":"https://api.github.com/users/mingelz/repos","events_url":"https://api.github.com/users/mingelz/events{/privacy}","received_events_url":"https://api.github.com/users/mingelz/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":13,"created_at":"2015-08-18T07:08:39Z","updated_at":"2015-12-09T09:25:15Z","closed_at":null,"body":"最近在做一个手机端页面时，遇到了一个奇怪的问题：字体的显示大小，与在CSS中指定的大小不一致。大家可以查看这个[Demo](http://s.codepen.io/mingelz/debug/Eadqgz)（记得打开Chrome DevTools）。\r\n\r\n![Font Boosting Test](https://cloud.githubusercontent.com/assets/339891/9324116/d7c37ef0-45b9-11e5-8e7d-5d882063f2f4.png)\r\n\r\n就如上图所示，你可以发现，原本指定的字体大小是24px，但是最终计算出来的却是53px，看到这诡异的结果，我心中暗骂一句：这什么鬼！\r\n\r\n随后开始对问题各种排查：某个标签引起的？某个CSS引起的？又或者是某句JS代码引起的。通过一坨坨的删代码，发现貌似都不是。我不禁又骂，到底什么鬼！不过中间还是发现了一些端倪：当页面中的标签数量或者文本数量大于某一个值，或者当CSS定义的字体大小落在某个区间时，这个问题才会被触发。而且字体变大后的值也随着原始定义的字体大小而改变。\r\n\r\n然后自然就是各种搜索，终于有了新的发现。原来这个特性被称做「Text Autosizer」，又称「Font Boosting」、「Font Inflation」，是 Webkit 给移动端浏览器提供的一个特性：当我们在手机上浏览网页时，很可能因为原始页面宽度较大，在手机屏幕上缩小后就看不清其中的文字了。而 Font Boosting 特性在这时会自动将其中的文字字体变大，保证在即不需要左右滑动屏幕，也不需要双击放大屏幕内容的前提下，也可以让人们方便的阅读页面中的文本。\r\n\r\n不过这个特性并不总是有必要的，还好在查到问题原因的同时，大家也讨论了对这个问题的一些处理方案：\r\n\r\n1. 手动指定 `viewport width=320`，这时 Font Boosting 不会被触发。（后边可以知道，这个说法不严谨，在其他设置均为默认值时，这一条才有效）\r\n2. Font Boosting 仅在未限定尺寸的文本流中有效，给元素指定宽高，就可以避免 Font Boosting 被触发。\r\n3. 显然第 2 条方案是有缺陷的，文本内容不可能都指定宽高。不过还好，我们通过指定 `max-height` ~~, `min-height`, `min-width`, `max-width`~~（经 @Ovaldi 指正，只有 `max-height` 有效） 也是可以的。比如 `body * { max-height: 999999px; }` 就可以无副作用的禁掉 Font Boosting 特性。当然，我觉得没必要使用通用选择器，用类似 `p { max-height: 999999px; }` 可能更好一些。\r\n\r\n到这里，我们已经明白问题所在，并且也有解决方案了。但是有一个问题仍然困扰着我：当字体大于某一个值时（比如当不指定viewport width，手机屏幕width=320，字体大于等于82px时），这个 Font Boosting 就始终不会被触发。Chrome 是如何计算的，这其中的逻辑又是什么？\r\n\r\n这一次问题解决起来就没有那么容易了，我先是各种搜索无果，然后自己人肉去试，慢慢找规律，但是发现变化不是线性的，看来这个公式还比较复杂。终于在今天被我发现了这篇文章：[Chromium's Text Autosizer](https://docs.google.com/document/d/1PPcEwAhXJJ1TQShor29KWB17KJJq7UJOM34oHwYP3Zg)，彻底解释了我的疑问。\r\n\r\nFont Boosting 具体的实现代码在 [TextAutosizer.cpp](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/layout/TextAutosizer.cpp) 这个文件中可以看到，有兴趣的可以翻一下。\r\n\r\n简单说来，Font Boosting 的计算规则伪代码如下：\r\n\r\n```javascript\r\nmultiplier = Math.max(1, deviceScaleAdjustment * textScalingSlider * systemFontScale * clusterWidth / screenWidth);\r\nif (originFontSize < 16) {\r\n    computedFontSize = originFontSize * multiplier;\r\n}\r\nelse if (16 <= originFontSize <= (32 * multiplier - 16)) {\r\n    computedFontSize = (originFontSize / 2) + (16 * multiplier - 8);\r\n}\r\nelse if (originFontSize > (32 * multiplier - 16)) {\r\n    computedFontSize = originFontSize;\r\n}\r\n```\r\n\r\n其中变量名解释如下，更具体的说明可以参考上边的两个链接。\r\n\r\n* `originFontSize`: 原始字体大小\r\n* `computedFontSize`: 经过计算后的字体大小\r\n* `multiplier`: 换算系数，值由以下几个值计算得到\r\n  * `deviceScaleAdjustment`: 当指定 `viewport width=device-width` 时此值为 1，否则值在 1.05 - 1.3 之间，有专门的计算规则\r\n  * `textScalingSlider`: 浏览器中手动指定的缩放比例，默认为 1\r\n  * `systemFontScale`: 系统字体大小，Android设备可以在「设备 - 显示 - 字体大小」处设置，默认为 1\r\n  * `clusterWidth`: 应用 Font Boosting 特性字体所在元素的宽度（如何确定这个元素请参考上边两个链接）\r\n  * `screenWidth`: 设备屏幕分辨率（DIPs, Density-Independent Pixels），如 iPhone 5 为 320\r\n\r\n说了这么多，貌似只需要记住 `p { max-height: 999999px; }` 就OK了。。。-_-!!!\r\n\r\n\r\n*Update 2015-7-24:*\r\n@yisibl 姐姐说，用 `max-height: 100%` 可能会更好一些。\r\n\r\n*Ref.*\r\n\r\n1. [Webkit Bug 84186](https://bugs.webkit.org/show_bug.cgi?id=FontBoosting) Webkit Bugs 上记录的这个问题，最早从 2012 年 4 月份就开始讨论这个问题了，但好像都没有引起我们的任何关注。\r\n2. [Chromium's Text Autosizer](https://docs.google.com/document/d/1PPcEwAhXJJ1TQShor29KWB17KJJq7UJOM34oHwYP3Zg) 关于 Font Boosting 最重要的一篇文章，更确切的说是论文。\r\n3. [Font boosting in mobile browsers](http://sysmagazine.com/posts/214559/)\r\n4. [Font Boosting](http://www.patrickcatanzariti.com/2013/03/font-boosting/) 一个俄国人用英文写的文章。\r\n5. 一堆 [StackOverflow](http://stackoverflow.com/search?q=font+boosting) 上的问答，用 Font Boosting 搜可以出来一大坨，这里就不列了。"},"comment":{"url":"https://api.github.com/repos/amfe/article/issues/comments/163159708","html_url":"https://github.com/amfe/article/issues/10#issuecomment-163159708","issue_url":"https://api.github.com/repos/amfe/article/issues/10","id":163159708,"user":{"login":"geeeeeeeeek","id":7262715,"avatar_url":"https://avatars.githubusercontent.com/u/7262715?v=3","gravatar_id":"","url":"https://api.github.com/users/geeeeeeeeek","html_url":"https://github.com/geeeeeeeeek","followers_url":"https://api.github.com/users/geeeeeeeeek/followers","following_url":"https://api.github.com/users/geeeeeeeeek/following{/other_user}","gists_url":"https://api.github.com/users/geeeeeeeeek/gists{/gist_id}","starred_url":"https://api.github.com/users/geeeeeeeeek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geeeeeeeeek/subscriptions","organizations_url":"https://api.github.com/users/geeeeeeeeek/orgs","repos_url":"https://api.github.com/users/geeeeeeeeek/repos","events_url":"https://api.github.com/users/geeeeeeeeek/events{/privacy}","received_events_url":"https://api.github.com/users/geeeeeeeeek/received_events","type":"User","site_admin":false},"created_at":"2015-12-09T09:25:15Z","updated_at":"2015-12-09T09:25:15Z","body":"感谢分享！Github Wiki在移动端也会autosize，原来是可以避免的。"}}