HTML+CSS34 1px边框问题的解决方案
1px边框问题的解决方案的总结
现象及原因
在移动端开发时,设计图中的1px
的边框,如果我们直接在CSS中设置边框的宽度为1px
,实际上在设备上显示的并不是1px
。这是因为不同的手机有着不同的像素密度,即window.devicePixelRatio
属性,它反应的是物理像素与逻辑像素的比值,IPhone6的dpr是2,也就是说,对于IPhone6来说,CSS的1px
显示时会显示为2px
的像素
当设置为1px的边框时,移动端的显示:
当设置为0.5px的边框时,移动端的显示:
PC端1px
的边框:
很明显看出,移动端1px
的边框更粗
媒体查询
要想解决这个问题,必须针对不同dpr的设备进行不同的处理,完全不必使用JavaScript,而是可以通过媒体查询实现
1 | @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2){ |
下面的各种处理方法,都是通过媒体查询进行分类处理,只列出2倍屏的处理方法,都省略了媒体查询的代码
解决方法1:伪元素 + tranform: scaleY
这种方法是比较常用,兼容性也比较好的,利用高度为1px
的伪元素来模拟边框,在媒体查询中利用tranform: scaleY
来进行缩放,需要设置transform: origin(0, 0)
保证缩放时伪元素距离父元素的距离
1 | h1 { |
- 优点:兼容性好,边框圆角也可以实现
- 缺点:代码量比较大,占据了伪元素,会引起冲突
解决方法2:0.5px
边框
直接将border
设置为0.5px
1 | .h1 { |
- 优点:简单直接
- 缺点:兼容性太差,安卓和低版本的IOS都不支持
解决方法3:伪元素 + liner-gradient
+ sacle
同样是利用伪元素实现,但是使用了liner-gradient
来模拟边框,实际上和第一种方法思路是相同的
1 | h1:after { |
解决方法4:通过viewport
实现
可以使用JavaScript来读取window.devicePixelRatio
,根据读取到的值来对<meat>
的viewport
进行改写,当dpr为2时,将页面缩放到原来的一半
1 | const dpr = window.devicePixelRatio; |
这样做可以直接使用px
来定义各处的尺寸,但是就不单单针对边框了,而是针对所有了,需要整体考虑
解决方法4:通过图片模拟
可以使用border-image
或者background-image
来加载预先设置好的边框图片
这种方法并不是很理想,因为修改颜色的时候都需要替换图片,并且如果边框有圆角的话也需要对图片特殊处理。
总结
从兼容性、针对性以及可维护性,还是使用伪元素 + tranform: scaleY
的第一种方法最为推荐,其他的方法要不是很麻烦,要不是原理相同。有一些文章介绍了七八种,有的能实现,但是实施起来很麻烦,有的根本就不能实现在移动端实现1px
,也不知道是我水平太低,还是作者根本没有亲自试验。