浏览器对「浮点型像素」的处理与造成的问题,以及对「可视区域」的探究

本文探讨了浏览器如何处理浮点型像素,特别是在非100%缩放的系统下。内容区和边框对于浮点像素的处理方式不同,且边框宽度的小数部分会导致一些显示问题。当内容区宽度小于0.5px时,浏览器会向上取整显示边框,而忽略内容区。此外,文章还研究了边框宽度变化对内容区定位的影响,揭示了浏览器在创建「可视区域」时的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浮点型像素,也就是带小数的像素,如1.6px,20.24px,0.5px等
但要注意的是:这里讨论的设备像素,是最终显示在电脑屏幕上的像素,而非css像素

出现浮点型像素的情况

1.电脑系统不是100%缩放,因为屏幕尺寸较小,如笔记本电脑,系统默认都是125%缩放,即使你的浏览器没缩放,css里的1px对应的也是1.25设备像素,就出现浮点型像素了(可能这也是版心最多是1200px的原因之一,1920px÷125%=1536px,125%缩放的电脑最多显示的css宽度其实是1536px,两边留的边距也就160px左右,版型再大就显得拥挤了)

2.css像素本身就是小数,可能是直接写的,如1.6px,这种情况不多;可能是单位为vw,rem,em换算成px时造成的小数,但是这要结合设备的缩放,比如125%的电脑上,0.8px对应的设备像素为0.8*125%=1px,小数css像素对应的反而是整数设备像素。或者是200%的手机上,0.5px对应的也是1设备像素。

3.浮点数计算精度不足,计算机的浮点数的位数限制导致计算并不精准,这在js的学习中就有所体会。
在这里插入图片描述

对浮点型像素的处理

(以谷歌浏览器为研究平台,以盒子模型为研究对象)

得到的结论:

内容区与内边距的像素边框的像素
四舍五入取整舍去小数,只取整数

注:特别地,无论是内容区还是边框,像素小于1px时,都会向上取整为1px。如border:0.1px solid #000;是用1设备像素显示的;width:0.1px;height:0.1px内容区也是用1设备像素显示,
但神奇的是同时写0.1px的宽高与边框,就只会显示边框而不会显示内容区,(原因是浏览器对「可视区域」的实现造成的,后面会说到)

实验代码与截图如下,左边截图为div在ps里放大的结果,右边是盒子模型(在100%系统缩放下实验)
----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------
0.1px的内容区仍然用1设备像素显示

div{
        width: 0.1px; height: 0.1px;
        border: 0px solid blue;		
        background-color: red;		
}

在这里插入图片描述在这里插入图片描述
注意:红色方块是一个像素点,在ps中放大的图像,其实它真实的样子如下图,
在这里插入图片描述
↑,睁大眼睛,他在这,1px就是这么小,所以后面的图像都是页面截图后ps放大的像素点图像

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------
1.49px的内容区仍然用1设备像素显示

div{
        width: 1.49px; height: 1.49px;
        border: 0px solid blue;		
        background-color: red;		
}

在这里插入图片描述在这里插入图片描述
----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------
1.51px的内容区用2设备像素显示

div{
        width: 1.51px; height: 1.51px;
        border: 0px solid blue;		
        background-color: red;		
}

在这里插入图片描述在这里插入图片描述
四舍五入了

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------
但是如果有1px宽的边框(蓝色),特殊情况就出现了

内容区宽高小于0.5px时,并没有向上取整为1px,也就是没显示内容,只显示边框,(后面我才知道,其实内容区在边框的下面,被盖住了)

div{
		/* 小于0.5px的内容区四舍五入为0px(设备像素) */
        width: 0.49px; height: 0.49px;
        border: 1px solid blue;		
        background-color: red;		
}

在这里插入图片描述在这里插入图片描述

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

div{
		/* 大于0.5px的内容区四舍五入为1px(设备像素) */
        width: 0.51px; height: 0.51px;
       	border: 1px solid blue;		
        background-color: red;		
}

在这里插入图片描述在这里插入图片描述
----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

接着是边框

边框的小数部分直接舍去

div{
		/* 边框的小数部分直接舍去*/
        width: 1px; height: 1px;
        border: 1.9px solid blue;
        background-color: red;		
        }

在这里插入图片描述在这里插入图片描述
这里内容区应该是1px却显示为3px,这是边框小数部分带来的问题,在下面讨论

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

小于1px的边框也是向上取整为1px(设备像素)

div{
			/* 小于1px的边框向上取整为1px(设备像素) */
            width: 1px; height: 1px;
            border: 0.1px solid blue;
            background-color: red;
        }

在这里插入图片描述在这里插入图片描述

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

对浮点型像素的处理而造成的问题

边框的小数部分并不是真的舍去,这个小数部分舍去,会造成1设备像素问题,这个小数在处理上也是四舍五入,大于0.5时会给内容区左侧与顶部各多加1设备像素,内容区右侧与底部有时(4css像素一个循环)也会出现多1设备像素的情况,有时border小数部分小于0.5也会出现,是和内容区的小数部分共同影响的。
----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

增加一个子元素,使其宽高等于父元素,背景黄色,也就是借助子元素使父元素的内容区显示出来
然后只改变父元素边框宽度,我尝试了很多值,但在这里只放有代表性的值

边框宽1.249px

.dad{
   	   width: 1px; height: 1px;
       border: 1.249px solid blue;		/* 下面的实验只改变这个 */
       background-color: red;
   }
.son{
	    width: 100%;
	    height: 100%;
	    background-color: yellow;		/* 子元素的作用是显示父元素的内容区 */
}

 <div class="dad">
	    <div class="son"></div>
    </div>

在这里插入图片描述在这里插入图片描述

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

边框宽1.25px

       border: 1.25px solid blue;

在这里插入图片描述在这里插入图片描述

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

边框宽1.49px

       border: 1.49px solid blue;

在这里插入图片描述在这里插入图片描述
这时发现内容区并没有增加,而是边框小数部分造成的影响,这就是1设备像素问题

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

边框宽1.51px

       border: 1.51px solid blue;

在这里插入图片描述在这里插入图片描述

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

边框宽1.749px

       border: 1.749px solid blue;

在这里插入图片描述
在这里插入图片描述

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

边框宽1.75px

border: 1.75px solid blue;

在这里插入图片描述在这里插入图片描述
----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

边框小数部分的取值范围0≤小数部分<0.250.25≤小数部分<0.50.5≤小数部分<0.750.75≤小数部分<1
造成的问题内容区右下出现1px空隙内容区左上出现1px空隙内容区四周出现1px空隙

边框小数部分的取值范围不同,造成的四种结果
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
同时测试了5.25px,23.34px等,结果相同,即边框整部分不影响这个一设备像素的问题
至于为什么出现这样的结果,一设备像素的问题,我当时完全没有思路,最后回头研究最开始时,为什么有边框,0.1px的内容区没有向上取整为1px显示,在我将边框透明化后,才发现问题所在——可视区域,我将边框透明后,边框原来的位置应该在视觉上“消失”才对,但结果边框原来的位置变成了背景的红色。我又将背景设为rgba()半透明,发现background-color这个值并不是只改变内容区与内边距的颜色,其实还包括边框的颜色,或者说background-color控制的是可视区域的颜色,然后因为层叠顺序上,边框在背景上方,所以边框的蓝色覆盖在可视区域的红色上。

这时候我才想到,为什么非要分开研究呢,难道不能将可视区域当作一个整体,研究浮点型像素的处理吗,

这样一想,问题立马解决了,
内容区宽高设为1px,边框在1px到2px改变,就有下表的结果
以高度为例,宽度是一样的

边框的取值范围1≤ border<1.251.25≤border<1.51.5≤border<1.751.75≤border<2
内容区的高度1px1px1px1px
上边框加下边框的高度[2,2.5)[2.5,3)[3,3.5)[3.5,4)
可视区域高度(内容区+上下边框)[3,3.5)[3.5,4)[4,4.5)[4.5,5)
可视区域高度,四舍五入3445
造成的问题内容区右下出现1px空隙内容区左上出现1px空隙内容区四周出现1px空隙

这是不是就解释了下面四个图的情况,3×3像素,4×4像素,4×4像素,5×5像素

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
还有一个问题就是内容区的定位问题,为什么代表内容区的黄色像素有时在左上有时在右下?
我猜测是浏览器按照层叠顺序,先绘制背景也就是可视区域,再绘制边框,再绘制内容区,也就是边框先占位置,内容再定位时要排除边框已经站的区域,比如说边框为1.5px,虽然浏览器不认这个小数部分,但是内容区却认,还将其四舍五入了,也就是内容区认为1.5px边框实际应该占2px,所以在可视区域的第二个像素处定位,而小于1.5px的边框,内容区将其四舍五入为1px,所以在可视区域的第一个像素处定位,
在这里插入图片描述
为了验证这个猜测,我在第四张图的基础上增加左上边框宽度,减小右下边框宽度,这样内容区就应该从第三个像素处定位
又出问题了,边框没事,可视区域没事,内容区出问题了,边框小数部分小于0.5px时,内容区会吞掉边框的小数,比如1.2px的内容区和1.3px边框,内容区会变成1.5px四舍五入变成2px宽,不写了,头疼

其实浏览器处理一个盒子模型时,最先计算的是可视区域这个总的值,也就是将边框、内边距与内容区全加在一起,最后四舍五入,就是可视区域的宽高,然后才是将内容区与边框一一定位在可视区域上,

而不是将边框、内边距、内容区都绘制到页面上后,他们占的总区域就是可视区域。我以前就是这么错误理解的,将可视区域理解为依附于盒子模型的一个抽象概念而已,毕竟学盒子模型时可没有一个叫可视区域的结构
我现在的理解时,盒子模型是w3c的标准,而这个标准是要浏览器实现的,在实现的过程中,浏览器真实的创造了可视区域这一个结构,注意这里说的结构而非概念。

----------------------分界线---------------------------------------------------------------------------------------------------------
----------------------分界线---------------------------------------------------------------------------------------------------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值