第期rem产生的小数像素问题

前言

最近一个活动页尝试用了上周推荐的宽窄屏自适应解决方案hot.css,在手机中遇到的坑就是在有的分辨率下会出现断横的情况,而且还有发现各种小数点的问题。所以今天来看看淘宝FED

颂晨的分享。

正文从这开始~

由于日常需求以无线居多,所以可以在业务中做一些尝试,如rem,刚接触这个特性的时候,曾经一度爱不释手,仿佛在无线开发的坎坷路上寻找到一条捷径。然而随着使用范围的扩大,慢慢的发现了一些使用rem带来的问题。

rem

关于rem这个单位的介绍,在此就不赘述,有兴趣的同学可以阅读一丝的《响应式十日谈第一日:使用rem设置文字大小》,文章对rem进行了详细的介绍。

用途

在无线开发中,响应式布局尤为重要,先不说屏幕尺寸越来越多样化的iPhone,单是安卓就有N多种尺寸要适配。

在没有使用rem之前,想要按照设计师的想法去适配不同分辨率1是一件非常难操作的事情。用了rem以后,一切简单了许多,你可以用它来设置元素的宽高、间距…,然后针对不同的分辨率计算并设置相对应的根字体大小,然后元素就好像缩放过一样自动适应了当前的分辨率,大大的降低了适配工作量。

Demo:

上图是同一个页面在AppleiPhone5和SamsungGalaxyS4两款机器下的效果,可以看出从px宽的iPhone5到px宽的S4,图片像是等比放大了一样,我们分析下这个原理:

1)假定2width=px的分辨率下的根字体大小是32px,由此推算:

2)width=px分辨率下:

3)根字体大小是32px,该分辨率下宽1rem的元素在浏览器里的真实宽度就是1*32=32px;

width=px分辨率下:

如果要达到等比放大的效果,宽1rem的元素在浏览器里的真实宽度就应该是32*(/)=36px,由此得出width=px分辨率下的根字体大小为36px;

由此可见等比缩放是通过控制根字体大小来实现的,且根字体大小与屏幕宽度成正比。

小数像素

刚才举的例子里面1rem在width=px分辨率下的真实尺寸为32px,在width=px分辨率下的真实尺寸为36px,均为整数。

如果是1.75rem呢?

可以看到部分机型下出现了小数像素,那么浏览器是如何处理小数像素的呢?

如图,第一组每个色块的大小为1.75remx1.75rem,第二组每个色块的大小为1.85remx1.85rem;

先看第一组色块,在iPhone6下,其在浏览器内的渲染尺寸应该是1.75*37.5=65.px;

但真实渲染尺寸却是另外一种情况:有的宽度是66px,有的却是65px,而且顺序上毫无规律。

这一结果让我十分疑惑,如果浏览器统一做四舍五入处理,那么所有的色块尺寸也应该是一样的,不会出现部分向上取整,部分向下取整。

思考许久无果,大胆设想了一下:浏览器在渲染时所做的舍入处理只是应用在元素的渲染尺寸上,其真实占据的空间依旧是原始大小。

也就是说如果一个元素尺寸是0.px,那么其渲染尺寸应该是1px,空出的0.px空间由其临近的元素填充;同样道理,如果一个元素尺寸是0.px,其渲染尺寸就应该是0,但是其会占据临近元素0.px的空间。于是就顺着这个思路验证了以下:

第一个色块的宽度为65.px,根据四舍五入的原则其最终渲染尺寸为66px,空出的0.px由第二个色块补上;

第二个色块向左补进0.px,相当于减少了0.px,余下65.25px,根据四舍五入的原则其最终渲染尺寸为65px,多出的0.25px会占用第三个色块的空间;

第三个色块被占用了0.25px,相当于增加了0.25px,等于65.px,根据四舍五入的原则其最终渲染尺寸为66px,空出的0.px由第四个色块补上;

第四个色块向左补进0.px,相当于减少了0.px,余下65.5px,根据四舍五入的原则其最终渲染尺寸为66px,空出的0.5px由第五个色块补上;

第五个色块向左补进0.5px,相当于减少了0.5px,余下65.px,根据四舍五入的原则其最终渲染尺寸为65px,多出0.px;

上述验证与浏览器输出结果完全一致,表明浏览器在处理小数像素的时候并不是直接舍入处理的,元素依旧占据着应有的空间,只是在计算元素尺寸的时候做了舍入处理(后来在看到LayoutUnit–WebKit这篇文档后,也印证了之前的假设)。

你可以参考上述原理对第二组色块进行验证,然后比对结果。

问题

目前遇到最多的问题就是background-image的问题,经常会因为小数像素导致背景图被裁掉一部分。

上图是同一组icon在不同机型下的效果,可以看出这些icon在iPhone5和GalaxyS4下或多或少的会被裁掉一部分,原因就是由于小数像素导致的,这点可以从元素的ComputedStyle上看出。

解决

如何避免这种问题呢?以下两点建议:

1)使用iconfont;

2)如需使用background-image,尽量为背景图设置一定的空白间隙,如图:

小结

小数像素产生的问题不单单只有background-image,还会有其他尚未遇到的坑,然而在了解了浏览器是如何处理小数像素的原理以后,此类问题就变得很好解决,也非常可控。

注:

文中出现的分辨率都是指浏览器分辨率,关于逻辑分辨率、物理分辨率之间的关系可以参考:「像素」「渲染像素」以及「物理像素」是什么东西?它们有什么联系?;

为了保证大部分分辨率下计算出的根字体大小都为整数,所以约定根字体大小的计算公式为:分辨率宽度/10;

注:早读君看评论,有人给出这样的方案:

雪碧图不能用rem.rem定位不准确。正确做法是。用js判断缩放比例。background-size和position都用px写死。然后动态增加.zoom{transform:scale(xxx)}样式。把使用到雪碧图的元素用zoom缩放。绝对不能在雪碧图用rem定位。小图建议base64

后语

1)通过这个活动遇到的坑就是在非公司产品环境中用这个解决方案毫无问题,一旦公司产品中,由于不识别viewport的为小于1的值,导致页面错乱了。最后采取的方案全部写死为1了。

2)欢迎大家把平时项目中遇到的问题以及解决方案分享給早读君!!因为分享是快乐的。

关于本文

作者:

颂晨

原文链接:


转载请注明:http://www.jinchangjk.com/afhhy/2372.html

当前时间: