移动端1px产生原因及解决方案

retina屏中,像素比为2(iPhone6/7/8)或3(iPhone6Plus/7Plus/8Plus),1px的边框看起来比真的1px更宽。

本文默认你已经对视口、物理像素、逻辑像素、设备像素比、css像素等移动端基本概念已经解。

产生原因

  • 设备像素比:dpr = window.devicePixelRatio = 物理像素 / 逻辑像素。
  • retina屏的手机上, dpr23css里写的1px宽度映射到物理像素上就有2px3px那么宽。
  • iPhone6dpr2,物理像素750(x轴),则它的逻辑像素为375。 也就是说,1个逻辑像素,在x轴和y轴方向,需要2个物理像素来显示,即:dpr=2时,表示1个CSS像素由4个物理像素点组成,如下图:
     

    需要给.tab添加1px的底部边框

 <div>
    <!-- 头部 -->
    <v-headers></v-headers>

    <div class="tab border-1px-bottom">
      <div class="tab-item">
        <router-link to='/goods'>商品</router-link>
      </div>
      <div class="tab-item">
        <router-link to='/ratings'>评论</router-link>
      </div>
      <div class="tab-item">
        <router-link to='/sellers'>商家</router-link>
      </div>
    </div>
    <!-- 路由组件显示 -->
    <router-view></router-view>

    <div class="footer">我是尾部</div>
  </div>

在vue项目中解决方式
我们在assets公共资源文件夹中新建stylus, 新建mixin.stylus,  利用伪类编写1px的边框, 并且对不同的设备像素比进行适配
// 伪类+transform
// 原理:把原先元素的border去掉,然后利用:before或者:after重做border,并 transform的scale缩小一半,
// 原先的元素相对定位,新做的border绝对定位。

$color = blue

.border-1px-bottom, .border-1px-top,.border-1px-left,.border-1px-right
  position: relative


// 边框一像素,利用伪类设置一像素
.border-1px::after
    content: "";
    box-sizing: border-box;
    position: absolute;
    left: 0;
    top: 0;
     100%;
    height: 100%;
    border: 1px solid $color

// 下边框
.border-1px-bottom::after
    position :absolute
    left: 0
    bottom: 0
     100%
    border-bottom: 1px solid $color
    content: ' '
    
// 上边框
.border-1px-top::before
    position :absolute
    left: 0
    top: 0
     100%
    border-top: 1px solid $color
    content: ' '


// 左边框
.border-1px-left::before
    position :absolute
    left: 0
    top: 0
    height: 100%
    border-left: 1px solid $color
    content: ' '


// 右边框
.border-1px-right::after
    position :absolute
    right: 0
    top: 0
    height: 100%
    border-right: 1px solid $color
    content: ' '


/*设备像素比*/
/*显示屏最小dpr为1.5*/
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
  .border-1px-bottom::after,.border-1px-top::before
    // Y轴压缩0.7,  1.5*0.7 约等于1
    -webkit-transform: scaleY(0.7)
    transform: scaleY(0.7)
  
  .border-1px-left::before,.border-1px-right::after
  // X轴压缩0.7,  1.5*0.7 约等于1
    -webkit-transform: scaleX(0.7)
    transform: scalexX(0.7)

  .border-1px::after 
     150%;
    height: 150%;
    transform: scale(0.7);
    transform-origin: 0 0;
    


@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
  .border-1px-bottom::after,.border-1px-top::before
    // Y轴压缩0.5,  2*0.5 等于1
    -webkit-transform: scaleY(0.5)
    transform: scaleY(0.5)
  
  .border-1px-left::before,.border-1px-right::after
  // X轴压缩0.5,  2*0.5 等于1
    -webkit-transform: scaleX(0.5)
    transform: scaleX(0.5)

  .border-1px::after 
     200%;
    height: 200%;
    transform: scale(0.5);
    transform-origin: 0 0;


@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
  .border-1px-bottom::after,.border-1px-top::before
    -webkit-transform: scaleY(0.333)
    transform: scaleY(0.5)
  
  .border-1px-left::before,.border-1px-right::after
    -webkit-transform: scaleX(0.333)
    transform: scaleX(0.333)

  .border-1px::after 
     300%;
    height: 300%;
    transform: scale(0.333);
    transform-origin: 0 0;
// 去除边框   // 
border-none()
  &:after
    display: none

然后在vue组件中的样式中引入

@import './assets/stylus/mixin.stylus'

在.tab的div中,添加border-1px-bottom类名即可

 <div class="tab border-1px-bottom">

如果要清除边框,在样式中调用该函数

 .info-item
        padding: 16px 12px
        line-height: 16px
        
        font-size: 12px
        &:last-child
          border-none()
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/fsg6/p/14351458.html