# 移动端 1px 问题

移动端 1px 问题是指,在 pc 端设置端 1px 边框样式在移动端上看上去比 1px 粗。 原因参考:
1px 像素问题 (opens new window)
解决方法参考:
移动端 1px 解决方案 (opens new window)

搬运其中 2 种比较好的解决方法:

# 使用伪元素

# 1 条 border

.setOnePx {
  position: relative;
  &::after {
    position: absolute;
    content: ' ';
    background-color: #e5e5e5;
    display: block;
    width: 100%;
    height: 1px; /*no*/
    transform: scale(1, 0.5);
    top: 0;
    left: 0;
  }
}

# 4 条 border

.setBorderAll {
  position: relative;
  &::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 #e5e5e5;
    border-radius: 4px;
  }
}
  • 优点:全机型兼容,实现了真正的 1px,而且可以圆角。
  • 缺点:暂用了 after 伪元素,可能影响清除浮动。

# 设置 viewport 的 scale 值

这个解决方案是利用 viewport+rem+js 实现的。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      html {
        font-size: 1px;
      }

      * {
        padding: 0;
        margin: 0;
      }

      .top_b {
        border-bottom: 1px solid #e5e5e5;
      }

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

      .a {
        width: 100%;
      }

      .b {
        background: #f5f5f5;
        width: 100%;
      }
    </style>
    <!-- <style>
    .a {
      position: relative;
    }

    .a::after {
      content: ' ';
      position: absolute;
      width: 200%;
      height: 200%;
      top: 0;
      left: 0;
      transform: scale(0.5);
      transform-origin: left top;
      /* 写成下面的形式也可以 */
      /* top: 50%;
      left: 50%;
      transform-origin: center;
      transform: translate(-50%, -50%) scale(.5); */
      box-sizing: border-box;
      border: 1px solid #e5e5e5;
      border-radius: 4px;
    }
  </style> -->
    <script>
      var viewport = document.querySelector('meta[name=viewport]');
      if (window.devicePixelRatio === 1) {
        viewport.setAttribute('content', 'width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-sclae=no');
      }
      if (window.devicePixelRatio === 2) {
        viewport.setAttribute('content', 'width=device-width,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-sclae=no');
      }
      if (window.devicePixelRatio === 3) {
        viewport.setAttribute('content', 'width=device-width,initial-scale=0.333333333333,maximum-scale=0.333333333333,minimum-scale=0.333333333333,user-sclae=no');
      }
      var docEl = document.documentElement;
      var fontSize = 32 * (docEl.clientWidth / 750) + 'px';
      docEl.style.fontSize = fontSize;
      // 首先,使用initial scale可以将页面大小整体缩小(缩小的比例由dpr决定),但是,我们的目标是只缩小border。
      // 因此,整体缩小给我们内容(padding、margin等)和文字大小带来了副作用,使用上面那个公式进行修正。
      // 750是一般设计稿的大小,16px是一般网页根字体的默认大小,上面那个将根字体修正为32px。
      // 此外,所有需要正常显示的内容文字全部根据rem计算,基于根字体。
    </script>
  </head>

  <body>
    <div class="top_b a">下面的底边宽度是虚拟1像素的</div>
    <div class="b">上面的边框宽度是虚拟1像素的</div>
  </body>
</html>
  • 优点:全机型兼容,直接写 1px 不能再方便
  • 缺点:适用于新的项目,老项目可能改动大