移动端 1px 问题的解决办法

导致原因

在PC端,CSS的1px一般对应着电脑屏幕的1个物理像素,但在移动端,CSS的1px等于
几个物理像素是和屏幕像素密度有关的。由于不同的手机有不同的像素密度,如
果移动显示屏的分辨率始终是普通屏幕的2倍,那1px 的边框在 设备像像素比(dpr)为 2 
的移动屏下会显示成 2px,所以在高清屏下看着1px总是感觉更粗

这里涉及到几个概念:

  1. 物理像素:也被称为设备物理像素,显示屏上最小的物理显示单元(像素颗粒)
  2. 设备独立像素:也被称为CSS像素,这个点代表一个可以由程序使用的虚拟像素, 有时也说是逻辑像素,然后由相关系统转换为物理像素
  3. 设备像素比(dpr) = 物理像素 / 设备独立像素(px)

解决办法

  1. 当设备像素比为 2 时,使用 0.5px

    优点:简单
    缺点:但是并不是所有手机浏览器都能识别到 border: 0.5px
    
  2. 伪类 + transform 实现: 把原生元素的border去掉,然后用:before或者:after重做border,并且使用transform 的 scale 属性缩小一半,原先的元素相对定位,新做的border绝对定位

    优点: 所有场景都能满足,支持圆角
    缺点: 对于已经使用伪类的元素,可能需要多层嵌套
    
    .element {
    	position: relative;
    	border: none;
    }
    // 下边框
    .element:after {
        content: "";
        position: absolute;
        bottom: 0;
        left: 0;
        background: steelblue;
        transform: scaleY(.5);
    }
    
  3. viewport + rem 实现

    优点: 这种兼容方案相比比较完美,所有场景都能满足,一套代码,可以兼容基本所有布局
    缺点: 适合新的项目,老的项目修改成本过大
    
    function resetRemUnit(){
    
      // 获得设备像素比
      var radio = window.devicePixelRatio;
      // 处理设备像素比,只能是1,2,3
      radio = radio >= 3 ? 3 : (radio >= 2 ? 2 : 1);
      // 判断是否有meta标签
      var viewportDOM = document.querySelector('meta[name=viewport]');
      if(!viewportDOM){
        viewportDOM = document.createElement('meta');
        viewportDOM.setAttribute('name', 'viewport');
      }
      // 计算页面缩放比例
      var scale = 1 / radio; 
      var content = 'width=device-width, initial-scale='+scale+', maximum-scale='+scale+', minimum-scale='+scale+', user-scalable=no';
      viewportDOM.setAttribute('content', content);
      // 添加meta标签
      document.head.appendChild(viewportDOM);
    
      // 控制计算rem的最大最小适配页面
      var min = 320 * radio;
      var max = 540 * radio;
      var width = document.documentElement.clientWidth || window.innerWidth || document.documentElement.getBoundingClientRect().width;
      if(width < min){
        width = min;
      }else if(width > max){
        width = max;
      }
      // 计算rem
      document.documentElement.style.fontSize = (width * 100 / 640) + 'px';
    }
    
    resetRemUnit();
    window.onresize = resetRemUnit;
    
  4. 使用 box-shadow模拟边框

     利用 css 对阴影处理的方式实现0.5px 的效果
     优点: 代码量少,可以满足所有场景
     缺点: 边框有阴影,颜色变浅
    
    .element {
    	box-shadow: inset 0px -1px 1px -1px steelblue;
    }
    
  5. 媒体查询 + transform 实现

    /* 2倍屏 */
    @media only screen and (-webkit-min-device-pixel-ratio: 2) {
        .border-bottom::after {
            -webkit-transform: scaleY(0.5);
            transform: scaleY(0.5);
        }
    }
    
发布了27 篇原创文章 · 获赞 37 · 访问量 2759

猜你喜欢

转载自blog.csdn.net/weixin_44691775/article/details/104440722