一、Viewport 基础

  • 移动端viewport meta 标签大致如下:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">

<!--
width:控制 viewport 的大小,可以指定的一个值,如果 600,或者特殊的值,如 device- width 为设备的宽度(单位为缩放为 100% 时的 CSS 的像素)。
height:和 width 相对应,指定高度。
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。
maximum-scale:允许用户缩放到的最大比例。minimum-scale:允许用户缩放到的最小比例。user-scalable:用户是否可以手动缩放
iphoneX的“刘海”为相机和其他组件留出了空间,同时在底部也留有可操作区域。两边会出现一道白条。
解决的方案是:1、给body添加一个background;2、添加viewport-fit=cover meta标签,使页面占满整个屏幕。
-->

二、window属性:devicePixelRatio

  • 该属性返回当前显示设备的物理像素分辨率与 CSS 像素分辨率的比率。此值也可以解释为像素大小的比率:一个 CSS 像素的大小与一个物理像素的大小的比值。简单地说,这告诉浏览器应该使用多少个屏幕的实际像素来绘制单个 CSS 像素。
// media媒体查询语法
.border-1px{ border: 1px solid #ccc; }
@media (-webkit-min-device-pixel-ratio: 2) {
    .border-1px{ border: 0.5px solid #ccc; }
}

三、解决方案:伪元素 + transform

  • 原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。
  • 完善 mixin.scss 函数
// app 1像素边框 
// $position:[边框位置]top, bottom, left, right 
// $color:[边框颜色] 
// $radius:[圆角] 
// 使用:@include border(top, #ddd); 或 @include border(full, #ddd, 2px);

@mixin border($position: full, $borderColor: #e2e2e2, $radius: 0) {
  content: ' ';
  position: absolute;
  pointer-events: none;
  color: $borderColor;

  @if $position==top {
    border-top: 1px solid $borderColor;
    height: 1px;
    left: 0;
    right: 0;
    top: 0;

    @media only screen and (-webkit-min-device-pixel-ratio:2) {
      & {
        -webkit-transform: scaleY(0.5);
        -webkit-transform-origin: 50% 0%;
      }
    }
  }

  @if $position==bottom {
    border-bottom: 1px solid $borderColor;
    height: 1px;
    left: 0;
    right: 0;
    bottom: 0;

    @media only screen and (-webkit-min-device-pixel-ratio:2) {
      & {
        -webkit-transform: scaleY(0.5);
        -webkit-transform-origin: 0 100%;
      }
    }
  }

  @if $position==left {
    border-left: 1px solid $borderColor;
    width: 1px;
    top: 0;
    bottom: 0;
    left: 0;

    @media only screen and (-webkit-min-device-pixel-ratio:2) {
      & {
        -webkit-transform: scaleX(0.5);
        -webkit-transform-origin: 0% 50%;
      }
    }
  }

  @if $position==right {
    border-right: 1px solid $borderColor;
    width: 1px;
    top: 0;
    bottom: 0;
    right: 0;

    @media only screen and (-webkit-min-device-pixel-ratio:2) {
      & {
        -webkit-transform: scaleX(0.5);
        -webkit-transform-origin: 100% 50%;
      }
    }
  }

  @if $position==full {
    border: 1px solid $borderColor;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: none;
    border-color: $borderColor;

    @if $radius !=0 {
      border-radius: $radius;
    }

    @media only screen and (-webkit-min-device-pixel-ratio:2) {
      & {
        right: -100%;
        bottom: -100%;
        -webkit-transform: scale(0.5);
        -webkit-transform-origin: 0% 0%;
        $radiusx2: null;

        @each $i in $radius {
          $radiusx2: append($radiusx2, $i * 2);
        }

        @if $radius !=0 {
          border-radius: $radiusx2;
        }
      }
    }
  }
}