1px问题解决方案总结

240

【本文目录】

  1. 前置概念
  2. 常见iPhone设备参数图
  3. 问题产生的根因
  4. 解决方案
  5. 总结

【前置概念】

屏幕尺寸:指的是屏幕对角线的长度

分辨率:是指宽度上和高度上最多能显示的物理像素点个数

点距:像素与像素之间的距离,点距和屏幕尺寸决定了分辨率大小

PPI:屏幕像素密度,即每英寸(1英寸=2.54厘米)聚集的像素点个数,这里的一英寸还是对角线长度

DPI:每英寸像素点,印刷行业术语。对于电脑屏幕而言和PPI是一个意思

设备像素(又称为物理像素): 指设备能控制显示的最小物理单位,意指显示器上一个个的点。从屏幕在工厂生产出的那天起,它上面设备像素点就固定不变了,和屏幕尺寸大小有关,单位 pt。

设备独立像素(也叫密度无关像素或逻辑像素):可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),这个点是没有固定下小的,越小越清晰,然后由相关系统转换为物理像素。

css像素(也叫虚拟像素):指的是 CSS 样式代码中使用的逻辑像素,在 CSS 规范中,长度单位可以分为两类,绝对(absolute)单位以及相对(relative)单位。px 是一个相对单位,相对的是设备像素(device pixel)

DPR(设备像素比):设备像素比 = 设备像素 / 设备独立像素。(在Retina屏的iphone上,DPR为2,1个css像素相当于2个物理像素)

【常见iPhone设备参数图】

【问题产生的根因】

在移动端开发的过程中这是必然要面临的一个问题。这个问题产生的原因就是*实际设备上2个或多个独立像素(可以简单理解为物理像素)*表示了1个逻辑像素(css中的px),导致了视觉上看到一的线条粗细和设计稿上的不符。

【解决方案】

  1. 利用伪元素::after + tranform 进行缩放(用伪元素的原因是因为伪元素是独立的元素,对齐缩放可以不影响目标元素)
  2. 利用媒体查询根据不同的DPR进行缩放
  3. 利用js 设置init-scale的值

利用伪元素::after + tranform 进行缩放

优点: 适合老项目,全机型兼容。

缺点:占用了伪元素

<div class="cell border-1px"> cell <div>

<style>
.cell {
    width: 100px;
    height: 100px;
}
<!--全部边框-->
.border-1px:after {
    content: '';
    position: absolute;
    box-sizing: border-box;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    border: 1px solid #000;
    border-radius: 4px;
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
    -webkit-transform-origin: top left;
}

<!--单边框,以上边框为例-->
.border-1px-top:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    border-top: 1px solid red;
    transform: scaleY(.5);
    transform-origin: left top;
}
</style>

利用媒体查询根据不同的DPR进行缩放

优点: 能实现。。。。

缺点: 麻烦且精确度不高

.border(
    @borderWidth: 1px;
    @borderStyle: solid;
    @borderColor: @lignt-gray-color;
    @borderRadius: 0) {
    position: relative;
    &:before {
        content: '';
        position: absolute;
        width: 98%;
        height: 98%;
        top: 0;
        left: 0;
        transform-origin: left top;
        -webkit-transform-origin: left top;
        box-sizing: border-box;
        pointer-events: none;
    }
    @media (-webkit-min-device-pixel-ratio: 2) {
        &:before {
            width: 200%;
            height: 200%;
            -webkit-transform: scale(.5);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 2.5) {
        &:before {
            width: 250%;
            height: 250%;
            -webkit-transform: scale(.4);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 2.75) {
        &:before {
            width: 275%;
            height: 275%;
            -webkit-transform: scale(1 / 2.75);
        }
    }
    @media (-webkit-min-device-pixel-ratio: 3) {
        &:before {
            width: 300%;
            height: 300%;
            transform: scale(1 / 3);
            -webkit-transform: scale(1 / 3);
        }
    }
    .border-radius(@borderRadius);
    &:before {
        border-width: @borderWidth;
        border-style: @borderStyle;
        border-color: @borderColor;
    }
}

.border-all(
	@borderWidth: 1px;
	@borderStyle: solid;
	@borderColor: @lignt-gray-color;
	@borderRadius: 0) {
    .border(@borderWidth; @borderStyle; @borderColor; @borderRadius);
}

利用js 设置init-scale的值

优点: 全机型兼容,方便

缺点: 不适合老项目

<html>
  <head>
      <title>1px question</title>
      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
      <meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
      <script>
          var viewport = document.querySelector("meta[name=viewport]");
          //下面是根据设备像素设置viewport
          viewport.setAttribute('content', `width=device-width,initial-scale=${1/window.devicePixelRatio}, maximum-scale=1, minimum-scale=1, user-scalable=no`);
      </script>
  </head>
</html>

总结:

新项目优先用:

js设置init-scale的方式解决

老项目优先用:

利用伪元素::after + tranform 进行缩放的方式解决

【参考文献】

www.cnblogs.com/yesyes/p/76…

www.jianshu.com/p/53074e846…