移动端一像素问题

移动端一像素问题

十月 15, 2018

最近公司项目要解决一像素问题,自己琢磨了一阵子并且网上搜索了一堆博客,总结出最好的办法应该是通过通过css的transform scale缩放1px的内容来模拟设备上1px的效果了。但是这个方法有太多局限。然后秉着css解决不了的问题就用js来解决的原则,然后结合vue的自定义指令,手撸了一个一像素vue自定义指令。打算扔到giuhub留存。顺便总结一下遇到的问题。

原因

众所周知,自从iPhone 4带来了Retina display后,移动端开始引入了一个叫设备像素比(devicePixelRatio)的东西。

另一方面,如果给一个html标签写一个小于1px(H5)的border;IOS可以正常渲染,但是安卓设备不渲染。所以是不能用正常的方法来让安卓设备渲染一个1物理像素的线。

(插入几个demo)

网上的解决方案

网上搜能搜出很多解决方案,这篇文章基本汇总了网上的所有方案。然后结论是:使用css的伪元素来渲染一个1px(H5)的div,并且使用CSS3的scale来缩放dpr,从而渲染一个1px物理像素的线。

然而理论毕竟理论,用到项目中的时候还是遇到了很多问题

不能渲染3边的border

网上的方案都是用CSS伪元素来实现的,而伪元素只有before和after两个,所以要实现3边1像素是不可能的。

必须手动设置圆角

如果遇到圆角是最头疼的问题。用CSS伪元素可以做到圆角,但是CSS伪元素只能通过border-radius: inherit得到和父元素一样值的圆角大小,无法计算缩放后还和父元素一样的圆角。而且js也不能操作CSS伪元素,所以不得不手动计算dpr,然后给CSS伪元素设置圆角。

-webkit-device-pixel-ratio不是标准方法

CSS中判断设备设备像素比的方法是-webkit-device-pixel-ratio,不是标准的方法,所以用起来心慌慌。而JS的window.devicePixelRatio已经全面支持,顶多也就一个undefined。完全不用担心兼容性问题。

部分标签不能设置伪元素

type为textinput标签就无法在标签内插入dom(虽然控制台里显示已经被插入,但是不会被渲染出来),所以伪元素也无法给其加上模拟的1像素。

更好的方案

本着CSS解决不了的问题就用JS来解决的思想。再结合Vue提供的自定义指令,可以在想要加1像素的html标签上加上一个指令

js能通过Vue的自定义指令拿到对应的DOM,那么就一切皆有可能。

总结