当你设置0.5px的边框宽度时...
为什么出现0.5px
我们在开发H5移动端页面时,UI提供的设计稿一般都是2倍图,750x1334尺寸的。然而实际的移动端设备大小,比如iphone6,其屏幕尺寸为375x667。这个时候设计稿中的1px,对应的屏幕尺寸应该写成0.5px。所以当我们直接设置成1px在实际的效果比设计稿都是要偏粗的。
这个时候如果没有思考更多的内容,往往会直接将1px修改成0.5px,可能这个时候你在部分浏览器里面能够看到自己想要的效果(比如我)但是后续在真实的手机浏览器或者其他手机内置浏览器上会发现当初设置的0.5px边框一部分消失了。
为什么不能设置0.5px
借着上述发生的边框设置失效的现象,来讨论一下为什么会出现这种问题?
一句话总结:跟不同设备的设备像素比有关DPR
设备像素比 = 物理像素 / CSS像素
物理像素
设备的物理像素是指在物理显示屏上实际存在的像素点的数量。它表示了显示屏的分辨率,即屏幕水平和垂直方向上的像素数量。
屏幕从工厂出来那天起物理像素点就固定不变了,也就是我们经常看到的手机分辨率所描述的数字。比如一个显示屏分辨率为1920x1080的设备,它的物理像素就是1920个水平像素和1080个垂直像素。
物理像素的密度决定显示屏的清晰度和细节展示能力,密度越高表示在屏幕上单位距离的物理像素点越多,也就是我们平时一直在说的要更高像素。在实际的开发过程中,很好的了解不同设备的物理像素,有利于我们在开发过程中进行更好的兼容和布局适配。
CSS像素
CSS像素是针在网页中使用的一种抽象单位,用于定义元素的尺寸和布局,并不直接对应设备的物理像素,而是在不同设备上通过缩放和转换来实现一致的效果。
CSS像素是一个相对单位,他的大小是跟设备的像素密度和缩放来决定的。在传统的显示器上,一般是一个CSS像素对应一个物理像素。但是随着技术的发展,屏幕的更新换代,一个CSS像素可能会对应多个物理像素,这里的多个其实就是指的设备像素比。比如现在iphone、三星、一加等手机都能上3或4的像素比。
那照上面来说,物理像素比高的话,0.5显示是不是也没什么问题呢?
- 不同的浏览器和设备在处理小数点可能会有不同的行为。有的浏览器会对小数点进行四舍五入或者直接取整,将0.5变成1,比如:Chrome 把 0.5px 四舍五入变成了 1px;而其他浏览器可能会进行向下取整,将其渲染为0像素。Firefox 会把不小于 0.55px 当成 1px,Safari 是把不小于 0.75px 当成 1px。同样在手机上ios的chrome可以画出0.5px的边,但是安卓部分系统的原生浏览器是不行的。
- 设备的物理像素是整数值,无法准确表示小数像素,这个时候如果当边框是0.5px时,浏览器可能会尝试通过在相邻像素之前均匀分布颜色来模拟半个像素的效果,这样可能会导致边框显示模糊或者失真。
由于上面的差异,我们在写0.5px时会产生不可预估的显示效果,为了保证更可预和更一致的显示效果,需要通过使用其他的方式解决这个问题。
如何解决这个问题
检测DPR动态调整
通过window.devicePixelRatio
判断能否处理0.5px边框动态给元素添加class
if(window.devicePixelRatio && window.devicePixelRatio >= 2){
...
}
这种方式并没有真正解决那些无法兼容的设备实现0.5px的效果,而且用了JS的方式去动态解决,不推荐。
使用box-shadow模拟边框
.box-shadow{
box-shadow: inset 0px -1px 1px -1px #000
}
这种方式虽然代码量少,而且使用纯css的方式解决问题 ,但是边框还是会有阴影的效果,颜色会变浅,并不能很好的还原border的UI效果。
viewport+rem实现
添加meta设置,同时通过设置对应的viewport的rem基准,这种方式就可以在后面的css代码中直接使用1px,比如:
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
这种方式是从整个项目页面统一做修改,这个针对现有的项目来说不是很友好,而且是属于全局的更改整个网页的缩放大小,个人也不是很推荐。
伪元素 + transform
如果是单条边框
将伪元素设置绝对定位,并且和父元素某个位置对齐,将width设置100%,height设置1px,然后进行Y方向的缩小0.5倍。
.article-comment-reply-top{position:relative}
.article-comment-reply-top::after{content:"\20";position:absolute;top:0;left:0;right:0;height:1px;background-color:#e8e8f3;-webkit-transform:scaleY(0.5);transform:scaleY(0.5)}
如果是整个四条边框
将伪元素进行绝对定位,并且将伪元素先放大2倍,然后设置边框,最后缩放到原来的0.5倍。
.follow-action{position:relative;border-radius:99px}
.follow-action:after{content:'';position:absolute;top:-50%;bottom:-50%;left:-50%;right:-50%;-webkit-transform:scale(0.5);transform:scale(0.5);border-style:solid;border-width:1px;border-color:#1a8cff;-webkit-border-radius:99px;border-radius:99px}
总结
我目前推荐的是伪元素+tranform缩放的方法,相对灵活一点,可以针对不同元素进行设置。
关于这个0.5px只是在H5开发中的一个很小很小的问题,我也只是针对这个问题做了部分展开,还有很多兼容性的问题或者一些很切实的H5开发小技巧需要在平时的学习和开发过程中发现和总结。尽量让自己在工作中少挖坑少填坑吧~😊
转载自:https://juejin.cn/post/7239897482103914555