移动端1px解决方案

1,367 阅读2分钟

前言

移动端web项目越来越多,设计师对UI要求越来越高,比如1px的边框。在高清屏下,移动端的1px会变粗。 比如下面: image.png

产生的原因

为什么会产生这个问题,主要是跟DPR(devicePixelRatio)设备像素比,他是默认缩放为100%的情况下,设备像素和css像素的比例

window.devicePixelRatio = 物理像素 / css像素

目前主流的屏幕DPR=2(iphone 8),或者3(iphone 8 plus)。拿2倍屏来说,设备的物理像素要实现1像素,而DPR=2,所以css像素只能0.5,一般设计稿是按照750来设计的,它上面的1px是以750来参照的,我们写的css样式是以设备375为参照的,所以我们应该写0.5px的就可以,但是ios8+系统才支持,安卓系统不支持。

解决方案

WWDC对ios系统给出方案

推荐指数:★★
在WWDC大会上,给出来了1px的方案,当写0.5px的时候,就会显示一个无力像素宽度的border,而不是css像素的border。所以在ios下,我们可以这样写。

border: 0.5px solid red;

总结:

  • 优点:简单,没有副作用
  • 缺点:支持ios8+,不支持安卓。

使用边框图片

推荐指数:★★

border: 1px solid transparent;
border-image: url('./image/border.jpg') 2 repeat;

总结:

  • 优点:没有副作用
  • 缺点:border颜色改变就的重新制作图片;圆角会比较模糊

使用box-shadow

推荐指数:★★★

box-shadow: 0  -1px 1px -1px red, 
    1px  0  1px -1px red,
    0  1px  1px -1px red,
    -1px 0  1px -1px red;

总结:

  • 优点:使用简单,圆角也可以实现
  • 缺点:模拟的实现方法,效果较好

使用伪元素

推荐指数:★★★★
同样为伪元素设置绝对定位,并且和父元素左上角对其,将伪元素的长宽放大为2倍,然后设置边框,左上角为中心,缩放到原来的0.5倍

.line5 {
    margin-top: 50px;
    position: relative;
    height: 60px;
}
.line5:after{
    content:" ";
    position:absolute;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    transform: scale(0.5);
    transform-origin: left top;
    box-sizing: border-box;
    border: 1px solid red;
    border-radius: 4px;
}

总结:

  • 优点:全机型兼容,实现了真正的1px,而且可以圆角
  • 缺点:占用了after伪元素,可能影响清除浮动

设置viewport的scale

推荐指数:★★★★★
利用viewport+rem+js实现的。

<html style="font-size: 12px;">
<head>
    <title>1px question</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <meta name="viewport" id="WebViewport"
        content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <style>
        * {
            padding: 0;
            margin: 0;
        }

        .line1 {
            width: 100%;
            border-bottom: 1px solid red;
        }

        .line1,
        .line2 {
            box-sizing: border-box;
            margin-top: 1rem;
            padding: 1rem;
            font-size: 1.4rem;
        }


        .line2 {
            background: red;
            width: 100%;
        }
    </style>
    <script>
        var viewport = document.querySelector("meta[name=viewport]");
        //下面是根据设备像素设置viewport
        if (window.devicePixelRatio == 1) {
            viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');
        }
        if (window.devicePixelRatio == 2) {
            viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');
        }
        if (window.devicePixelRatio == 3) {
            viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');
        }
        var docEl = document.documentElement;
        var fontsize = 36 * (docEl.clientWidth / 750) + 'px';
        docEl.style.fontSize = fontsize;
    </script>
</head>

<body>
    <div class="line1">下面的底边宽度是虚拟1像素的</div>
    <div class="line2">上面的边框宽度是虚拟1像素的</div>
</body>

</html>

总结:

  • 优点:全机型兼容,直接写1px
  • 缺点:适用于新的项目,老项目可能改动大