浏览器对css小数点的处理
近期在开发的时候遇到一个奇怪的问题,如下图(ios系统,android暂未发现),第一个和第三个子元素中的角标与父元素始终有一条缝隙,但是第二个没有,因为第一次遇到,没有意识到是小数点的问题,然后从头到尾重新看了相关的样式,布局,设置都没有问题,但是那条缝又明明确确的在那儿
核心代码:
ul { display: flex; justify-content: space-between; padding: 15px; li { position: relative; width: 32%; ... span { position: absolute; right: 0; top: 0; ... } } }
秉着实践出结果,开始调试(iphone6),所有布局相关的样式一个个改值,最后在同事的帮助下,发现把width改为31.5%之后就可以了,此时意识到与css小数点有关系
于是针对这个来分析(下面分析仅仅作为参考,浏览器内核到底怎么工作的,safari和chrome又分别做了什么暂不清楚):
iphone6宽度为375px,ul宽度为345px,所以32%和31.5分别是110.4和108.675,果然四舍五入之后,前者变小后者变大。网上查找之后说是,浏览器会对css小数点有不同的处理规则,ie向下取整,chrome,safari等四舍五入,参考这两篇文章css布局单元 ,css小数像素问题
大致了解为什么会出现这种情况之后,针对自己这个问题,从深层次的角度分析一下原因,见上述参考链接,webkit内核在渲染元素时,真实渲染区域是固定不变的,但是在文档流中的空间大小是计算出来的,所以直接影响到了下一个元素,出现了第二个元素与第一个元素表现形式不同的情况。如下图是webkit计算方式:
按照上面计算方式计算宽度为32%时,三个元素的结果如下:
- 第一个li,x = 15,width = round(15+110.4) - round(15) = 110
- 第二个li,x = 125.4,width = round(125.4+110.4) - round(125.4) = 111
- 第三个li,x = 235.8,width = round(235.8+110.4) - round(235.8) = 110
我们可以发现,第一个li,实际渲染区域宽度为110.4,但是文档流中宽度为110,所以子元素可活动区域为110,那0.4便是那条空隙
第二个li,实际渲染区域也是110.4,但是文档流中宽度为111,同理第三个计算为110,这便也解释了为什么一三表现形式一样
同理,宽度为31.5时,width分别为:109,109,109,实际渲染宽度为108.675
经过测试验证,ios系统内,safari和应用内webview效果与分析一致,但是通过dom获取元素width时,与上面计算结果不一致,全部都是四舍五入之后的结果,这一点没有搞清楚。但是通过分析验证了问题所在,之后遇到这种情况的时候便有了解决办法:
- 合理设置百分比,使其计算结果小数点>=5,进而四舍五入之后宽度大于实际渲染宽度