1.Flexible原理
- 1.1设置viewport
通过设置scale将viewport宽度设置为实际的设备物理宽度, css里的1px就等于实际物理设备1px。
例如iphone6 设备像素比devicePixelRatio=2,flexible设置的meta信息如下:
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
iphone6没有设置scale之前(375px) x (667px),1个css像素由2 x 2个物理像素构成,设置scale之后viewport大小为(750px) x (1334px),iphone6是二倍屏,从而实现css1px等于实际1px。1px就是设备展示的最小单位了。通常ui给的1px就是物理设备的最小单位(下图中红色部分标注的部分),flexible很好的实现了在iphone上的1px线条,直接设置height: 1px即可。
- 1.2 设置rem
Flexible将屏幕宽度等分10份,html元素上的font-size设置为1rem, 1rem = 屏幕宽度 / 10, 例如iphone6中1rem = 750px / 10 = 75px, css需要将px转化为rem, 从而实现不同屏幕的适配。
2. 安卓下1px问题
Flexible只处理了IOS机型,非iOS机型还是采用传统的scale=1.0,原因是在于安卓手机不一定有devicePixelRatio属性,以及devicePixelRatio的不规范,导致Flexible放弃治疗。所以在安卓的高清屏幕上1px显示比较粗,例如安卓3倍屏,1px会用3行物理像素点展示如下图所示。比ios的1px宽了许多。
解决方案:判断若为安卓机型,给html添加样式如下
// flexible.js
function retina () { // android高分辨率屏幕处理
if (navigator.userAgent.toUpperCase().indexOf('IPHONE OS') !== -1) return;
var classNames = [];
var pixelRatio = window.devicePixelRatio || 1;
classNames.push('pixel-ratio-' + Math.floor(pixelRatio));
if (pixelRatio >= 2) {
classNames.push('retina');
}
var html = document.getElementsByTagName('html')[0];
classNames.forEach(function (className) {
html.classList.add(className);
});
}
...
// css文件
.border {
...
height:1px;
html.pixel-ratio-2 & {
transform: scaleY(0.5)
}
html.pixel-ratio-3 & {
transform: scaleY(0.3)
}
}
ps:在iphone下设置0.5px(小于最小的物理像素单位)依然有线条展示,在android下设置0.5px是不会展示的。
为什么小于最小的物理像素单位还会展示线条呢?
其实展示的依然是最小的物理像素单位,不同的浏览器处理小于1px的方式不同,有些采用四舍五入,有些大于某个值展示1px否则就不展示,有些只是线条的颜色变浅了,从视觉上看就变细了。对比处理效果如下图所示。