2018_10_21_01.md 4.7 KB

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() {})
div {
    border: 1px solid #bbb;
}
.hairlines div {
    border-width: 0.5px;
}

使用 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;
    }
}

使用 background-image 实现

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

多背景渐变实现

.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;
}

使用 box-shadow 模拟边框

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

viewport + rem 实现

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

在devicePixelRatio = 3 时,输出viewport:
```html

这种兼容方案相对比较完美,适合新的项目,老的项目修改成本过大。对于这种方案,可以看看《使用 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;
}

四条 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;
}
if (window.devicePixelRatio && devicePixelRatio >= 2) {
    document.querySelector("ul").className = "scale-1px";
}