[聚合文章] retina屏中1物理像素border的实现

CSS 2017-11-20 13 阅读

问题的产生

retina屏会以2个(乃至3个)物理像素来显示一个CSS像素(1px),所以在CSS中指定1px的边框实际占据的却是2个以上物理像素,在retina屏用户体验较差。

几种解决方案(考虑1px=2dip)

使用0.5px

问题:只在Firefox and Safari 8+支持,安卓不支持。

使用图片

采用一张图片作为border:

border-width: 1px;
border-image: url(border.gif) 2 repeat;

border-img属性会将图片(如上图)切为九宫格,放到边框的四边和四角。由于图片外沿一半为实色、一半为透明,所以1px的图片边框,实际显示出的就是0.5px的边框了。

问题:

  • 无法设置颜色
  • 边框实际还是占用了1px的空间
  • 不使用base64的情况下,要加载多一张图片

使用渐变

原理类似上面的图片,将1px的渐变拆为两半,一半透明一半实色,但好处是作为背景不会实际占据盒子的0.5px空间。

background: linear-gradient(180deg, black, black 50%, transparent 50%) top left / 100% 1px no-repeat,
            linear-gradient(90deg, black, black 50%, transparent 50%) top right / 1px 100% no-repeat, 
            linear-gradient(0, black, black 50%, transparent 50%) bottom right / 100% 1px no-repeat, 
            linear-gradient(-90deg, black, black 50%, transparent 50%) bottom left / 1px 100% no-repeat;

问题:无法处理圆角

使用缩放

给一个原元素两倍大小的伪元素,指定1px边框,再缩小一半,即可得到0.5px边框。

.retina-border-scale {
    position: relative;
}
.retina-border-scale:before {
    content: '';
    border: 1px solid black;
    transform: scale(0.5);
    transform-origin: 0 0;
    width: 200%;
    height: 200%;
    position: absolute;
    left: 0;
    top: 0;
}

问题:

  • 原元素需要用相对定位
  • <td> 元素上不起作用

其他方法

  • 使用box-shadow:实现简单,但效果不好、会有阴影
  • 直接按照放大的设计稿重构,再指定viewport的initial-scale=0.5缩小整个页面:简单粗暴

对非retina屏的兼容

由于非retina屏下的1物理像素border直接用px做单位即可,因此针对不同屏幕,会有多套样式实现。

而为了正确地应用样式,首先得有判断retina屏的能力。这其中,CSS的媒体查询里提供了 min-device-pixel-ratio或min-resolution ;而浏览器也提供了 window.devicePixelRatio 这个js API来获取CSS像素和物理像素的比值。

最后,我们就可以根据屏幕在代码里应用适当的样式了。

ref

CSS, Retina, and Physical Pixels

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。