flexible.js字体大小诡异现象解析及解决方案
最近在做一个手机端页面时,遇到了一个奇怪的问题:字体的显示大小,与在CSS中指定的大小不一致。大家可以查看这个Demo(记得打开Chrome DevTools)。

就如上图所示,你可以发现,原本指定的字体大小是24px,但是最终计算出来的却是53px,看到这诡异的结果,我心中暗骂一句:这什么鬼!
随后开始对问题各种排查:某个标签引起的?某个CSS引起的?又或者是某句JS代码引起的。通过一坨坨的删代码,发现貌似都不是。我不禁又骂,到底什么鬼!不过中间还是发现了一些端倪:当页面中的标签数量或者文本数量大于某一个值,或者当CSS定义的字体大小落在某个区间时,这个问题才会被触发。而且字体变大后的值也随着原始定义的字体大小而改变。
然后自然就是各种搜索,终于有了新的发现。原来这个特性被称做「Text Autosizer」,又称「Font Boosting」、「Font Inflation」,是 Webkit 给移动端浏览器提供的一个特性:当我们在手机上浏览网页时,很可能因为原始页面宽度较大,在手机屏幕上缩小后就看不清其中的文字了。而 Font Boosting 特性在这时会自动将其中的文字字体变大,保证在即不需要左右滑动屏幕,也不需要双击放大屏幕内容的前提下,也可以让人们方便的阅读页面中的文本。
不过这个特性并不总是有必要的,还好在查到问题原因的同时,大家也讨论了对这个问题的一些处理方案:
- 手动指定
viewport width=320,这时 Font Boosting 不会被触发。(后边可以知道,这个说法不严谨,在其他设置均为默认值时,这一条才有效) - Font Boosting 仅在未限定尺寸的文本流中有效,给元素指定宽高,就可以避免 Font Boosting 被触发。
- 显然第 2 条方案是有缺陷的,文本内容不可能都指定宽高。不过还好,我们通过指定
max-height,(经 @Ovaldi 指正,只有min-height,min-width,max-widthmax-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: 浏览器中手动指定的缩放比例,默认为 1systemFontScale: 系统字体大小,Android设备可以在「设备 - 显示 - 字体大小」处设置,默认为 1clusterWidth: 应用 Font Boosting 特性字体所在元素的宽度(如何确定这个元素请参考上边两个链接)screenWidth: 设备屏幕分辨率(DIPs, Density-Independent Pixels),如 iPhone 5 为 320
说了这么多,貌似只需要记住 p { max-height: 999999px; } 就OK了。。。-_-!!!
用 max-height: 100% 可能会更好一些。
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">
flexible.js字体大小诡异现象解析及解决方案的更多相关文章
- 配合sublime使用flexible.js实现微信开发页面自适应
什么是flexible.js 是一个终端设备适配的解决方案.也就是说它可以让你在不同的终端设备中实现页面适配. 是一个用来适配移动端的javascript框架.根据宽度的不同设置不同的字体大小,样式间 ...
- hotcss.js Flexible 移动端适配在dpr=2和dpr=3出现的字体大小设置不正确问题.
这段时间一直在用hotcss做移动端适配,做了几个页面没有发现什么问题,后来老大要加快进度,我把项目分出一块给另一个同事做,她发现了一个问题就是字体在dpr=2,dpr=3,的设备上字体大小显示老是不 ...
- 改变字体大小实现自适应之js方案A
一.元素大小有两种写法 1.写结果:设计师给的移动端页面sketch设计稿一般是750px宽度,在sublime编辑器里,设置cssrem或rem-unit插件为56px的字体大小.做页面时,设计稿是 ...
- html页面控制字体大小的js代码
dom对象控制显示文章字体大小的js代码 <head> <script type="text/javascript"> function check(siz ...
- WebStorm 在 Mac 版本的基本设置,包括 ES6、Node.js、字体大小等
WebStorm 在 Mac 和 win 的设置有区别,便于以后用到快速查找,记之. 要设置先点击 WebStorm 字样如下图: 后点击 Preferences 字样如下图: 设置 es6 语法, ...
- 应用js改变问章字体大小
刚来公司的时候领导给分配的都是一些简单的简单的简单的.....任务 一次叫我把文章的字体大小变换功能写出来.在网上搜了很多都不管用!不过功夫不负有心人还是被我找到了!拿出来分享下! <scrip ...
- js控制手机端字体大小rem
//得到手机屏幕的宽度 let htmlWidth = document.documentElement.clientWidth || document.body.clientWidth; if(ht ...
- 【前端开发】禁止微信内置浏览器调整字体大小的方法js
微信webview内置了调整字体大小的功能,用户可以根据实际情况进行调节.但是很多移动端页面的开发都是使用rem作为单位的,字体大小改变以后,会出现页面布局错乱的情况,因此希望能够禁止微信的字体放大功 ...
- 用js判断屏幕的宽度,改变html字体大小用rem布局
if (document.documentElement.clientWidth > 600) {//页面宽度大于600px让其宽度等于600px,字体大小等于60px,居中 document. ...
随机推荐
- C#Equal的使用
代码如下: public partial class FramMain : Form { public FramMain() { InitializeComponent(); } private vo ...
- C语言随记-1
涉及指针.数组.函数指针 几种声明形式 int *a[5]; // a是一个有5个元素的数组,每个元素是整数类型指针(int *) int *a[] = {0x100, 0x104, 0x108, 0 ...
- 程序员的家!我终于拥有自己的blog了!!!
经过多次提交诚恳的家园申请,终于得到了审核通过!今天就开始了我的.net成长之路!!!
- (转)log4net使用详解
说明:本程序演示如何利用log4net记录程序日志信息.log4net是一个功能著名的开源日志记录组件.利用log4net可以方便地将日志信息记录到文件.控制台.Windows事件日志和数据库(包括M ...
- js获取get值
//获取get值 function getPar(par) { //获取当前URL var local_url = document.location.href; //获取要取得的get参数位置 va ...
- (原)torch7中添加新的层
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6069627.html 参考网址: http://torch.ch/docs/developer-doc ...
- MFC 多线程
MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息 队列和消息循环. 工作者线程没有消息机制,通 ...
- 搭建hbase-0.94.26集群环境
先安装hadoop1.2.1,见http://blog.csdn.net/jediael_lu/article/details/38926477 1.配置hbase-site.xml <prop ...
- CentOS和Ubuntu的区别
CentOS(Community ENTerprise Operating System)是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码规定释出的源代 ...
- python保留两位小数
python保留两位小数: In [1]: a = 5.026 In [2]: b = 5.000 In [3]: round(a,2) Out[3]: 5.03 In [4]: round(b,2) ...