• 移动端1px边框的问题


    今天解决一下移动端1px边框的问题,顺便集合下解决方案。

    造成边框变粗的原因

    css中的1px并不等于移动设备的1px,这是由不同手机由不同像素密度,在window对象中有一个devicePixelRatio属性,他可以反应css中像素与设备的像素比
    devicePixelRatio 的官方给的定义为: 设备物理像素和设备独立像素的比例,也就是devicePixelRatio = 物理像素 / 独立像素。

    解决方案

    1、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;
    }
    
    

    2、使用border-image实现

    准备一张符合要求的border-image

    底部边框

    .border-bottom-1px{
      border-width: 0 0 1px 0 ;
      border-image: url(linenew.png) 0 0 2 0 stretch;
      -webkit-border-image: url(linenew.png) 0 0 2 0 stretch;
    }
    
    

    把border设置在底部,图片2px高,上面1px颜色透明,下面1px使用规定的border颜色

    3、使用background-image实现

    和border-image实现类似,需要事先准备好图片

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

    缺点:

    修改颜色麻烦,需要替换图片
    圆角需要特别处理,边缘会模糊

    4、利用多背景渐变实现

    与background-image类似,把图片改成渐变的背景,一半设置颜色,一半设置透明

    .background-gradient-1px{
      background:
        line-gradient(180deg, black,black 50%, transparent 50%) top left / 100% 1px no-repeat;
        line-gradient(90deg, black,black 50%, transparent 50%) top right / 1px 100% no-repeat;
        line-gradient(0, black,black 50%, transparent 50%) bottom right /  100% 1px no-repeat;
        line-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-step(.5,transparent),
                    color-step(.5,#c8c7cc), to(#c8c7cc)) left bottom repeat-x;
        background-size: 100% 1px;
    }
    
    

    5、利用box-shadow模拟边框

    css阴影的方式处理

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

    6、viewport + rem 实现

    同时通过设置对应的viewport的rem基准值, 解决了1像素bug

    这种方式比较完美,对老版本的修改不友好

    优点:所有场景都能满足,一套代码,可以兼容所有布局

    缺点:老项目修改代价过大

    // 在devicePixlRatio = 1 时, 输出viewport
    <mate name="viewport" content="initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
          
    // 在devicePixlRatio = 2 时, 输出viewport
    <mate name="viewport" content="initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">
      
    // 在devicePixlRatio = 3 时, 输出viewport
    <mate name="viewport" content="initial-scale=0.333333,maximum-scale=0.333333,minimum-scale=0.333333,user-scalable=no">
    
    
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <meta
          name="viewport"
          content="width=device-width,initial-scale=1,user-scalable=no"
        />
        <title>rem+viewport适配</title>
        <style type="text/css">
          * {
            margin: 0;
            padding: 0;
          }
          #box {
            width: 8rem;
            height: 8rem;
            border: 1px solid #000;
          }
        </style>
      </head>
      <body>
        <div id="box"></div>
      </body>
      <script type="text/javascript">
        //获取dpr
        var dpr = window.devicePixelRatio; // 2
        console.log(dpr, 'dpr+++');
        //比例              // 0.5
        var scale = 1 / dpr;
        var width = document.documentElement.clientWidth; //375
        //3.通过dpr让元素进行缩放,initial-scale=0.5
        var metaNode = document.querySelector('meta[name="viewport"]');
        metaNode.setAttribute(
          'content',
          'width=device-width,initial-scale=' + scale + ',user-scalable=no'
        );
        var width = document.documentElement.clientWidth; //750
        //4.布局元素 单位 rem ,反向把缩放比例乘回来  2
        var styleN = document.createElement('style');
        styleN.innerHTML = 'html{font-size: ' + width / 16 + 'px !important;}';
        document.head.appendChild(styleN);
      </script>
    </html>
    
    

    7、使用伪类+transform实现

    对于老项目,这种方案比较完美, 原理是把原来的所有边框去掉,通过伪类崇左border,并且transform的scale缩小一半,原先的单挑border样式设置

    .scale-1px{
      position:relative;
      border:none;
    }
    .scale-1px:after{
      content: '';
      position:absolute;
      bottom:0;
      background: #000;
      width:100%;
      height:1px;
      transform:scale(0.5);
      transform-origin: 0 0;
    }
    
    .scale-1px-top {
      /* border-bottom: 1px solid rgb(229, 229, 229); */
      /* box-shadow: inset 0px -1px 1px -1px #c8c7cc; */
      border:none;
      position:relative;
    }
    .scale-1px-top:before{
      content: '';
      position: absolute;
      display:block;
      top: 0;
      left: 0;
      width: 200%;
      height: 1px;
      border-top: 1px solid #E7E7E7;
      -webkit-transform: scale(0.5,0.5);
      transform: scale(0.5,0.5);
      -webkit-transform-origin: 0 0;
      transform-origin: 0 0;
    }
    
    .scale-1px-bottom {
      /* border-bottom: 1px solid rgb(229, 229, 229); */
      /* box-shadow: inset 0px -1px 1px -1px #c8c7cc; */
      border:none;
      position:relative;
    }
    .scale-1px-bottom:before{
      content: '';
      position: absolute;
      display:block;
      bottom: -1px;
      left: 0;
      width: 200%;
      height: 1px;
      border-bottom: 1px solid #ccc;
      -webkit-transform: scale(0.5,0.5);
      transform: scale(0.5,0.5);
      -webkit-transform-origin: 0 0;
      transform-origin: 0 0;
    }
    
    .borderRadius-1px {
      /* border-bottom: 1px solid rgb(229, 229, 229); */
      /* 圆角(伪类和本体类都需要加border-radius) */
      border-radius:.16rem;
      border:none;
      position:relative;
    }
    .borderRadius-1px:after{
      /* 圆角(伪类和本体类都需要加border-radius) */
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      border: 1px solid #d1d1d1;
      -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;
      border-radius:.16rem;
    }
    
    

    8 、svg

    <svg width=100% height=1   style="position: absolute;bottom: 0;left: 0;">
     <line x1="0" y1="0" x2="1000" y2="0" style="stroke:#E5E5E5;stroke-width:1" />
    </svg>
    
  • 相关阅读:
    使用Transformer实现自动调制识别(RML2016.10a,90%+精度(未调参优化))
    美味的黄油如果不冷藏,会变质吗?
    芒果汁行业调研:2022年市场规模及产量分析
    嵌入式分享合集37
    vs2013调试的时候我想查看某个变量的值的窗口被我删了,我需要找到那个查看局部变量的值的窗口
    基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(一)
    帝国CMS的Sitemap网站地图生成插件下载及教程
    【笔记】samba shell 脚本 离线安装 - Ubuntu 20.04
    python 里面对于字典进行key或value排序输出
    [C++][vtk][转载]利用vtk绘制文本
  • 原文地址:https://blog.csdn.net/weixin_45403802/article/details/140373615