关于rem布局详细可以看看大漠这篇
关于像素的概念可以看看这篇
以下是自己rem布局中的一些体会
由于历史原因在pc端的视口默认为980px,注意这里是css像素,也叫逻辑像素,也等于设备独立像素,在移动端下,屏幕物理像素(也叫设备像素)的分辨率提高了,那么pc端显示在移动端下时,1物理像素就可以显示更多的css像素,那么pc端的页面等于被缩小了,为了解决这个不对称,在meta标签加上一个width=device-width,就可以让css像素等于屏幕物理像素。
即使这样,在移动端还是有些问题,假如在750设计稿下盒子的border=1px,那么在iphone6,7,8下,border永远不会等于1,在iphone6,7,8下border会变为2px,在对应的plus下border会变为3px,使用手淘的适配方案,在iphone的二倍屏三倍屏下,
meta的显示如下:
二倍屏<meta content="inital-scale=0.5">
三倍屏<meta content="inital-scale=0.3333">
原理其实就是让rem变大2倍或3倍,在通过meta把页面缩小为0.5倍或0.3333倍,虽然可以解决1px的问题,但会造成其它问题,例如你的页面中有嵌入iframe的第三方课件或者广告,别人不一定按照你的布局方式,那么有可能第三方页面会被你缩小,我觉得适配还是要写成
<meta content="inital-scale=1">
在二倍三倍屏下对border=1px的处理可以通过css3的scale属性处理,当然scale会缩放这个元素,最好把'border=1px'转为伪元素,通过scale缩放伪元素,scale缩小为0.5倍或0.3333倍取决于二倍屏还是三倍屏,通过下面函数给html节点增加对应的 选择器来判断
function retina () { // 二倍三倍分辨率屏幕处理
var docEl = document.documentElement;//获取html节点
docEl.className='';//清空选择器
var class_arr = [];//存放选择器名字
var pixel_ratio = window.devicePixelRatio || 1;//判断几倍屏
class_arr.push('pixel-ratio-' + Math.floor(pixel_ratio));//把几倍屏的选择器存放数组里
if (pixel_ratio >= 2) {//二倍三倍屏幕多存放选择器retina
class_arr.push('retina');
}
class_arr.forEach(function (className) {//循环选择器到html节点
docEl.classList.add(className);
});
}
如果是一条边框可以通过以下方式(css简略写,理解就会了)
.pixel-ratio-2 .box{
position: relative;
}
.pixel-ratio-2 .box::before{
position: absolute;
bottom: 0;
left: 0;
right: 0;
border-bottom: 1px solid red;
transform: scale(0.5);
}
pixel-ratio-3 .box{
position: relative;
}
.pixel-ratio-3 .box::before{
position: absolute;
bottom: 0;
left: 0;
right: 0;
border-bottom: 1px solid red;
transform: scale(0.333333);
}
如果是四条边框可以通过以下方式,边框和宽高通过放大原来的几倍,在缩小几倍
.pixel-ratio-2 .box{
position: relative;
}
.pixel-ratio-2 .box::before{
position: absolute;
bottom: 0;
left: 0;
right: 0;
width: 200%;
height: 200%;
border: 2px solid red;
transform: scale(0.5);
transform-origin: 0 0;
}
.pixel-ratio-3 .box{
position: relative;
}
.pixel-ratio-3 .box::before{
position: absolute;
bottom: 0;
left: 0;
right: 0;
width: 300%;
height: 300%;
border: 3px solid red;
transform: scale(0.333333);
transform-origin: 0 0;
}
关于rem布局参考网上并结合自己的理解修改,如下
;(function(designWidth, maxWidth) {
var doc = document,
win = window,
docEl = doc.documentElement,
tid;
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
maxWidth = maxWidth || 540;
width>maxWidth && (width=maxWidth);
var rem = width * 100 / designWidth;
docEl.style.fontSize =rem + 'px';
retina();
}
//要等 viewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
refreshRem();
win.addEventListener("resize", function() {
clearTimeout(tid); //防止执行两次
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener("pageshow", function(e) {
if (e.persisted) { // 浏览器后退的时候重新计算
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
function retina () { // 二倍三倍分辨率屏幕处理
docEl.className='';//清空选择器
var class_arr = [];//存放选择器名字
var pixel_ratio = window.devicePixelRatio || 1;//判断几倍屏
class_arr.push('pixel-ratio-' + Math.floor(pixel_ratio));//把几倍屏的选择器存放数组里
if (pixel_ratio >= 2) {//二倍三倍屏幕多存放选择器retina
class_arr.push('retina');
}
class_arr.forEach(function (className) {//循环选择器到html节点
docEl.classList.add(className);
});
}
if (doc.readyState === "complete") {
doc.body.style.fontSize = "16px";
} else {
doc.addEventListener("DOMContentLoaded", function(e) {
doc.body.style.fontSize = "16px";
}, false);
}
})(750, 750);
关于1px的处理有很多种方式,淘宝京东网易苏宁都采用了不同的方式,但每种都有其局限性的一面,了解其实现原理并且结合业务场景,找到适合自己的为佳!