欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
sticky 空白
 
最近在开发过程中遇到一个有意思的现象,当使用 sticky position 定位的时候,如果它的同层上面元素的高度是浮点数的话,该定位在滑动过程中将会产生一个小的空白间隙。
 
例如布局代码:
 
<div class="app">
 
 <div class="header">
 
   这块如果高度是浮点,将会在黏住的时候,留下间隔
 
 </div>
 
 <div class="content">
 
   <div class="slider">
 
     这块如果高度是浮点,将会在黏住的时候,留下间隔
 
   </div>
 
   <div class="filter"></div>
 
   <div class="footer"></div>
 
 </div>
 
</div>
 
css 布局代码如下:
 
body {
 
 margin: 0;
 
 padding: 0;
 
 background: white;
 
 overflow: auto;
 
}
 
.app {
 
 height: 10000px;
 
}
 
.header {
 
 position: -webkit-sticky;
 
 position: sticky;
 
 top: 0;
 
 height: 50px;
 
 background: green;
 
}
 
.slider {
 
 height: 70.9px;  /* 注意这里是一个浮点数 */
 
 background-color: pink;
 
}
 
.slider-content {
 
 height: 71px;
 
}
 
.content {
 
 height: 850px;
 
 background-color: yellow;
 
}
 
.filter {
 
 position: -webkit-sticky;
 
 position: sticky;
 
 top: 50px;
 
 height: 50px;
 
 background-color: red;
 
}
 
.footer {
 
 height: 40.9px; /* 这里的不会产生空白 */
 
 background-color: #fff;
 
}
 
filter 元素采用 sticky 定位后,slider 元素的高度为浮点数,在页面往上滑动的过程中,将会产生一个1px的空白间隙。导致滑动过程中可以看见底层的元素,对用户体验不是很友好,在线演示地址:sticky 浮点数字布局
 
但是当布局采用 fixed 或 position 定位的时候并不会出现这样的问题,这里应该是和浏览器处理小数渲染问题有关,这里暂且认为是一个 sticky 布局的 bug(有知道具体的原因的请告诉我)。
 
目前如果要解决这个问题,采用的方法是等页面全部布局好之后,动态将影响 sticky 布局元素的同级上层元素高度设置为整数。不过这也让我对浏览器处理小数渲染产生兴趣,那么浏览器怎么渲染小数或者百分比呢?
 
保留个数
 
浏览器在处理小数点个数的时候,如果元素宽度为 30.33333333px。通过 getComputedStyle 得到的宽度是 30.32812px,保留了后五位小数,当然由于计算机并不能精准的表示小数,所以才会有这样的结果。通过比较后,看出 getComputedStyle 输出有效数是 6 位(macos chrome)。
 
具体可以通过查看 Alex Kilgour 的 带小数位的百分比、像素测试页面。
 
渲染规则
 
在一般的业务开发中,我们手写宽度,一般很少写到小数点,不过如果在业务中用到了 rem 布局方案的话,会面临到这个问题,插件会帮你自动转变 px 为 rem,就会产生小数的问题。因为根据 html 的 font-size 来确定元素宽高的话,不一定都是整数。理想的渲染当然是能渲染出真实的宽度,但是屏幕是由像素点构成的,只能渲染出单个像素点(或者亚像素渲染)。在浏览器中,对于小数的处理有各自不同的方案,归纳起来大概有 3 种,往下取整,四舍五入,智能补偿。
 
往下取整:浏览器会直接忽略小数点部分,真实渲染后宽度为往下取整的宽度,例如一个元素宽为 208.8px。渲染到屏幕上宽度为 208px。
 
四舍五入:顾名思义,就是当宽度为浮点数时,会将宽度进行取舍处理得到整数,最终渲染出来。例如:width 是 208.4px 的 208.6px 的宽度。
 
智能补偿:前面 2 种主要是早期浏览器的行为,现代浏览器会智能计算各个 div 的宽度。先采用四舍五入将计算结果拿到真是的值,然后将不足的或者超过的补偿给下个元素。例如 3 个宽度为 208.4px 的 div 并排在一起。
 
注意看第 2 个 208.4px 的元素,当你用 offsetWidth 去拿渲染后的值的时候,会得到 209px。实际上采用的计算方法是补偿计算,及前一个多出的 0.4px 会增加到后一个元素上,所以第二个得到 208.8px。四舍五入为 209px。多渲染出的 0.2px 会在下一个元素上减去。第三个计算后为 208.2px。真是渲染为 208px,以此类推。
 
亚像素渲染
 
前面提到过浏览器渲染是一个像素一个像素渲染的,就导致在处理小数的时候,实际会渲染为一个真实小数点,不会还有一种渲染技术被称为亚像素渲染。简单说,一个像素是由红绿蓝三原色组成的。而该技术能单独独立控制红绿蓝晶体管的开关。这样一个像素能被控制的精度提高了 3 倍。
 
该技术最长用在字体的渲染上面,如果你通过软件截图,把字体放大后发现字体周围有彩色边框,那么该文字既是采用了亚渲染技术。可以发现用了该技术,字体看上去更加清晰,察觉不到锯齿了。
 
而浏览器在布局元素的时候,也会采用亚渲染技术。不过该技术由于需要将屏幕控制开关精确到三原色晶体管。就会更加消耗电量。而且该技术本质上是想通过细粒度的开关,来软提高分辨率,减少锯齿感。但是目前的设备分辨率都十分的高了,开启和关闭该技术对人的感知不是很大。所以在手机等移动设备上一般默认是关闭的。
 
总结
 
不同的浏览器对于小数的处理并不十分一致,现代浏览器大多采用智能补偿法来处理小数的布局。同时我们常用的 1px 并不是指的真实的 1 像素。比如在手机上 1px 渲染出来会比较粗,并不是手机分辨率的 1 像素。可以通过缩放来呈现真实的 1 像素。
 
理解了小数的渲染规则,希望以后如果碰到相似的问题对你有帮助。

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h63560.shtml