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