# # 1px 边框问题

7 种方法解决移动端 Retina 屏幕 1px 边框问题

在 retina 屏中实现 1px border 效果

#### # 下文出自7 种方法解决移动端 Retina 屏幕 1px 边框问题

### # 造成边框变粗的原因

其实这个原因很简单，因为 css 中的 1px 并不等于移动设备的 1px，这些由于不同的手机有不同的像素密度。在 window 对象中有一个 devicePixelRatio 属性，他可以反应 css 中的像素与设备的像素比。

> devicePixelRatio 的官方的定义为：设备物理像素和设备独立像素的比例，也就是 devicePixelRatio = 物理像素 / 独立像素。

### # 0.5px 边框

    if (window.devicePixelRatio && devicePixelRatio >= 2) {
        var testElem = document.createElement("div");
        testElem.style.border = ".5px solid transparent";
        document.body.appendChild(testElem);
        if (testElem.offsetHeight == 1) {
            document.querySelector("html").classList.add("hairlines");
        }
        document.body.removeChild(testElem);
    }
    // 脚本应该放在内，如果在里面运行，需要包装 $(document).ready(function() {})

1
2
3
4
5
6
7
8
9
10

    div {
        border: 1px solid #bbb;
    }
    .hairlines div {
        border-width: 0.5px;
    }

1
2
3
4
5
6

### # 使用 border-image 实现

    /* 底部边框 */
    .border-bottom-1px {
        border-width: 0 0 1px 0;
        -webkit-border-image: url(linenew.png) 0 0 2 0 stretch;
        border-image: url(linenew.png) 0 0 2 0 stretch;
    }
    /* 上下边框 */
    .border-image-1px {
        border-width: 1px 0;
        -webkit-border-image: url(linenew.png) 2 0 stretch;
        border-image: url(linenew.png) 2 0 stretch;
    }
    /* 使用Media Query做兼容 */
    .border-image-1px {
        border-bottom: 1px solid #666;
    }
    @media only screen and (-webkit-min-device-pixel-ratio: 2) {
        .border-image-1px {
            border-bottom: none;
            border-width: 0 0 1px 0;
            -webkit-border-image: url(../img/linenew.png) 0 0 2 0 stretch;
            border-image: url(../img/linenew.png) 0 0 2 0 stretch;
        }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

### # 使用 background-image 实现

    .background-image-1px {
        background: url(../img/line.png) repeat-x left bottom;
        -webkit-background-size: 100% 1px;
        background-size: 100% 1px;
    }

1
2
3
4
5

### # 多背景渐变实现

    .background-gradient-1px {
        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;
    }
    /* 或者 */
    .background-gradient-1px {
        background: -webkit-gradient(
                linear,
                left top,
                left bottom,
                color-stop(0.5, transparent),
                color-stop(0.5, #c8c7cc),
                to(#c8c7cc)
            ) left bottom repeat-x;
        background-size: 100% 1px;
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

### # 使用 box-shadow 模拟边框

    .box-shadow-1px {
        box-shadow: inset 0px -1px 1px -1px #c8c7cc;
    }

1
2
3

### # viewport + rem 实现

同时通过设置对应 viewport 的 rem 基准值，这种方式就可以像以前一样轻松愉快的写 1px 了。在 devicePixelRatio = 2 时，输出 viewport：

    在devicePixelRatio = 3 时，输出viewport：
    ```html

1
2

这种兼容方案相对比较完美，适合新的项目，老的项目修改成本过大。对于这种方案，可以看看《使用 Flexible 实现手淘 H5 页面的终端适配》

### # 伪类 + transform 实现

单条 border 样式设置：

    .scale-1px {
        position: relative;
        border: none;
    }
    .scale-1px:after {
        content: "";
        position: absolute;
        bottom: 0;
        background: #000;
        width: 100%;
        height: 1px;
        -webkit-transform: scaleY(0.5);
        transform: scaleY(0.5);
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

四条 boder 样式设置:

    .scale-1px {
        position: relative;
        margin-bottom: 20px;
        border: none;
    }
    .scale-1px:after {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        border: 1px solid #000;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        width: 200%;
        height: 200%;
        -webkit-transform: scale(0.5);
        transform: scale(0.5);
        -webkit-transform-origin: left top;
        transform-origin: left top;
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

    if (window.devicePixelRatio && devicePixelRatio >= 2) {
        document.querySelector("ul").className = "scale-1px";
    }

1
2
3