备战面试!最简单有效的解决移动端1PX的问题

248 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

为什么移动端会出现1px的问题?

css的1px在PC端就是1px; 在移动端就往往就大于 1px

产生原因

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

解决方式实现原理:伪元素 + transform 缩放

<!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>1px 问题</title>
<style>
    body {margin:0;padding:19px}
    div { padding:1em;margin:1em;}
    .box1{border-top: 1px solid #000;}
    .box2{position: relative;border-bottom:1px solid #000;}
    .box2::after{
        content:'';
        position: absolute;
        left:0;top:0;width: 100%;
        height: 1px; 
        background-color: #000;
        transform: scaleY(0.5);
    }
</style>
</head>
<body>
<div class="box1">
    1px的上边框
</div>

<div class="box2">
    0.5px的上边框
</div>
</body>
</html>

伪元素::after::before独立于当前元素,可以单独对其缩放而不影响元素本身的缩放 移动端项目组肯定不止一处用到,所以我们可以封装成公共样式文件

// src/assets/styles/hairline.scss
@mixin scale-hairline-common($color, $top, $right, $bottom, $left) {
content: '';
position: absolute;
display: block;
z-index: 1;
top: $top;
right: $right;
bottom: $bottom;
left: $left;
background-color: $color;
}
@mixin hairline($direction, $color: #000, $radius: 0) {
@if $direction == top {
border-top: 1px solid $color;

// min-resolution 用来检测设备的最小像素密度
@media (min-resolution: 2dppx) {
  border-top: none;

  &::before {
    @include scale-hairline-common($color, 0, auto, auto, 0);
    width: 100%;
    height: 1px;
    transform-origin: 50% 50%;
    transform: scaleY(0.5);

    @media (min-resolution: 3dppx) {
      transform: scaleY(0.33);
    }
  }
}
} @else if $direction == right {
border-right: 1px solid $color;

@media (min-resolution: 2dppx) {
  border-right: none;

  &::after {
    @include scale-hairline-common($color, 0, 0, auto, auto);
    width: 1px;
    height: 100%;
    background: $color;
    transform-origin: 100% 50%;
    transform: scaleX(0.5);

    @media (min-resolution: 3dppx) {
      transform: scaleX(0.33);
    }
  }
}
} @else if $direction == bottom {
border-bottom: 1px solid $color;

@media (min-resolution: 2dppx) {
  border-bottom: none;

  &::after {
    @include scale-hairline-common($color, auto, auto, 0, 0);
    width: 100%;
    height: 1px;
    transform-origin: 50% 100%;
    transform: scaleY(0.5);

    @media (min-resolution: 3dppx) {
      transform: scaleY(0.33);
    }
  }
}
} @else if $direction == left {
border-left: 1px solid $color;

@media (min-resolution: 2dppx) {
  border-left: none;

  &::before {
    @include scale-hairline-common($color, 0, auto, auto, 0);
    width: 1px;
    height: 100%;
    transform-origin: 100% 50%;
    transform: scaleX(0.5);

    @media (min-resolution: 3dppx) {
      transform: scaleX(0.33);
    }
  }
}
} @else if $direction == all {
border: 1px solid $color;
border-radius: $radius;

@media (min-resolution: 2dppx) {
  position: relative;
  border: none;

  &::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: 200%;
    height: 200%;
    border: 1px solid $color;
    border-radius: $radius * 2;
    transform-origin: 0 0;
    transform: scale(0.5);
    box-sizing: border-box;
    pointer-events: none;
  }
}
}
}
// 移除边框
@mixin hairline-remove($position: all) {
@if $position == left {
border-left: 0;
&::before {
  display: none !important;
}
} @else if $position == right {
border-right: 0;
&::after {
  display: none !important;
}
} @else if $position == top {
border-top: 0;
&::before {
  display: none !important;
}
} @else if $position == bottom {
border-bottom: 0;
&::after {
  display: none !important;
}
} @else if $position == all {
border: 0;
&::before {
  display: none !important;
}
&::after {
  display: none !important;
}
}
}

后面我们需要使用,直接在某个scss文件中导入即可 格式

选择器 {
@include hairline(参数,xxxx)
}

实际使用

@import '~@scss/hairline.scss';
.box1 {
 margin: 10px 0;
 position:relative;
 @include hairline(bottom, #000); // 添加边框
// 移除边框
// @include hairline-remove(bottom); 
}