1.如何解决 1px 问题

189 阅读2分钟

1px 问题指的是:移动端页面的 1px 会变的很粗,呈现出不止 1px 的效果。

为什么会存在 1px 问题?

自从 2010 年 iPhone4 推出了 Retina(视网膜) 屏开始,移动设备屏幕的像素密度越来越高,于是便有了 2 倍屏、3 倍屏的概念。在一些 Retina(视网膜) 屏幕 的机型上,移动端页面的 1px 会变的很粗,呈现出不止 1px 的效果。

即:CSS 中的 1px 并不能和移动设备上的 1px 画等号,它们之前的比例关系如下:

设备像素比dpr: window.devicePixelRatio = 设备的物理像素 / CSS 像素

例如:

打开 chrome 控制台,启动移动端调试模式, 输入 window.deviceRixelRatio,输出 2,此时移动端设备选择的是 iPhone XR。

意味着设置的 1px CSS像素,在这个设备上实际上会用 2 个 物理像素单元进行渲染,所以实际上看到的一定会比 1px 粗一些。

如何解决 1px 问题?

方法一:直接把 1px 改成 1/devicePixelRatio 的值

这是目前为止最简单的一种方法,先通过 js 拿到 window.deviceRixelRatio, 然后把这个值通过jsc 或者模板语法给到 css 的 data里。这种方法的缺陷在于兼容性不行,IOS 系统需要 8 及 以上的版本,安卓系统则直接不兼容。

<div 
    class='test' 
    data-device={{window.deviceRixelRatio}}>
</div>
// css 样式
.test[data-device='2']{  
    border: 0.5px solid #eee;
}

方法二:伪元素先放大后缩小

思路是先放大、后缩小:在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后,整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的 2 倍,border 值设为 1px。 接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的 50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border 也缩小为了 1px 的二分之一,间接地实现了 0.5px 的效果。

这个方法的可行性会更高,兼容性也更好。唯一的缺点是代码会变多。

代码如下:

.test[data-device='2'] {  
    position: relative;
}
.test[data-device='2']::after{  
    position: absolute;  
    top:0;  
    left: 0;  
    width: 200%;  
    height: 200%;  
    content:"";  
    transform: scale(0.5);  
    transform-origin: left top;  
    box-sizing: border-box;  
    border: 1px solid #eee;
}