为何会变粗
如iphone 5s,2倍高清屏,css上使用的border:1px对应的是设备独立像素,而此时,这1px会被转成4个物理像素(放大2倍,如下图)。所以,在手机上看到的边框(横向)其实是占用了2个物理像素的高度(如果有对比的话,会非常明显感觉边框高了一倍)。同理在3倍高清屏上,也是一样。
解决的方法都是差不多,使用其他元素来替代border,然后根据不同的屏幕来缩放大小,2倍就50%,3倍就33.333%。

物理像素(physical pixel)
物理像素又被称为设备像素,他是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果。
设备独立像素(density-independent pixel)
设备独立像素也称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素。
CSS像素
CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。一般情况之下,CSS像素称为与设备无关的像素(device-independent pixel),简称DIPs。
设备像素比(device pixel ratio)
设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:
设备像素比 = 物理像素 / 设备独立像素
1、使用scale
举个例子,现在要做一个上边框 border-top ,这里是用了伪类元素:before来模拟这条上边框,样式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| div.ui-border-top:before { content: ''; position: absolute; left: 0; top: 0; bottom: auto; right: auto; height: 1px; width: 100%; background-color: #c8c7cc; display: block; -webkit-transform-origin: 50% 0%; transform-origin: 50% 0%; }
|
然后就需要根据不同的屏来缩放大小,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @media screen and (-webkit-min-device-pixel-ratio: 2){ div.ui-border-top:before { -webkit-transform: scaleY(0.5); transform: scaleY(0.5); } } @media screen and (-webkit-min-device-pixel-ratio: 3){ div.ui-border-top:before { -webkit-transform: scaleY(0.33); transform: scaleY(0.33); } }
|
2、使用gradient
这种方法的局限性比较大,因为需要使用到元素的背景属性,大概的思路就是利用渐变,来达到线条变小了的效果(其实只是看起来小了)。
1 2 3 4 5 6 7 8 9 10
| @media screen and (-webkit-min-device-pixel-ratio: 2){ div.ui-border-top { width: 100px; height: 100px; margin: 0 auto; background-size: 100% 1px; background-repeat: repeat-x; background-position: left top; background-image: -webkit-linear-gradient(bottom, transparent, transparent, #ddd); }
|
在线Demo
如果需要适配3倍高清屏,就需要把渐变再分细一层。
3、制作圆角边框
同样使用伪类元素:before来代替。因为有圆角,所以上面提到的方法就行不通了,那么这里使用的方法就是制作一个2倍大小的元素(对应2倍高清屏),然后缩小一倍,来达到1px边框的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @media screen and (-webkit-min-device-pixel-ratio: 2){ .ui-border-radius:before { content: ""; width: 200%; height: 200%; position: absolute; top: 0; left: 0; border: 1px solid #e0e0e0; -webkit-transform: scale(0.5); -webkit-transform-origin: 0 0; padding: 1px; -webkit-box-sizing: border-box; border-radius: 8px; pointer-events: none; } }
|
4、@supports
@supports并不是规范,兼容性也不乐观。但在iOS9里,可以直接使用0.5px,还是非常方便的。
1 2 3 4 5 6
| @supports(display: flex){ .demo{ border: 0.5px solid #ddd; } }
|
5、总结
整个实现的方法都是通过使用别的元素来模拟边框,然后根据不同的屏幕来缩放,建议使用伪类元素来替代,这样就不会影响到html的元素布局。(ps:以上的方法并未进行兼容测试,不过可以默认webkit内核的都可以,部分渣渣安卓手机可能也不太兼容!)
参考资料:frozenui
参考资料:Flexible