适配方案
- 固定高度,宽度自适应
垂直方向使用固定的值,水平方向使用弹性布局,元素采用定值、百分比、flex布局等。这种方案相对简单,还原度也非常低。
<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
- 固定布局视口宽度,使用viewport进行缩放
这个适配也不友好,pc端和移动端
var win = window,
width = 640,
iw = win.innerWidth || width,
ow = win.outerHeight || iw,
sw = win.screen.width || iw,
saw = win.screen.availWidth || iw,
ih = win.innerHeight || width,
oh = win.outerHeight || ih,
ish = win.screen.height || ih,
sah = win.screen.availHeight || ih,
w = Math.min(iw, ow, sw, saw, ih, oh, ish, sah),
ratio = w / width,
dpr = win.devicePixelRatio;
if (ratio = Math.min(ratio, dpr), 1 > ratio) {
var ctt = ",initial-scale=" + ratio + ",maximum-scale=" + ratio,
metas = document.getElementsByTagName("meta");ctt += "";
for (var i = 0, meta; i < metas.length; i++) meta = metas[i], "viewport" == meta.name && (meta.content += ctt)
}
- 根据不同屏幕动态写入font-size, 以rem作为宽度单位,固定布局视口
/**
* 以下这段代码是用于根据移动端设备的屏幕分辨率计算出合适的根元素的大小
* 当设备宽度为375(iPhone6)时,根元素font-size=16px; 依次增大;
* 限制当为设备宽度大于768(iPad)之后,font-size不再继续增大
* scale 为meta viewport中的缩放大小
*/
(function (doc, win) {
var docEl = win.document.documentElement;
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
/**
* ================================================
* 设置根元素font-size
* 当设备宽度为375(iPhone6)时,根元素font-size=16px;
× ================================================
*/
var refreshRem = function () {
var clientWidth = win.innerWidth
|| doc.documentElement.clientWidth
|| doc.body.clientWidth;
console.log(clientWidth)
if (!clientWidth) return;
var fz;
var width = clientWidth;
fz = 16 * width / 375;
docEl.style.fontSize = fz + 'px';
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, refreshRem, false);
doc.addEventListener('DOMContentLoaded', refreshRem, false);
refreshRem();
})(document, window);
- 根据不同屏幕动态写入font-size和viewport,以rem作为宽度单位
将屏幕分为固定的块数10:
var width = document.documentElement.clientWidth; // 屏幕的布局视口宽度
var rem = width / 10; // 将布局视口分为10份
这样在任何屏幕下,总长度都为10rem。1rem对应的值也不固定,与屏幕的布局视口宽度有关。
对于动态生成viewport,他们原理差不多,根据dpr来设置缩放。看看淘宝的:
var devicePixelRatio = window.devicePixelRatio;
var isIPhone = window.navigator.appVersion.match(/iphone/gi);
var dpr,scale;
if (isIPhone) {
if (devicePixelRatio >=3) {
dpr = 3;
} else if (devicePixelRatio >=2) {
dpr = 2;
} else {
dpr = 1;
}
} else {
dpr = 1;
}
scale = 1 / dpr;
注意
- 1px 问题
var dpr, scale, timer, rem;
var style = document.createElement('style');
dpr = window.devicePixelRatio || 1;
scale = 1 / dpr;
document.documentElement.setAttribute('data-dpr', dpr);
var metaEl = document.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'target-densitydpi=device-dpi, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
document.documentElement.firstElementChild.appendChild(metaEl);
document.documentElement.firstElementChild.appendChild(style);
if (980 === document.documentElement.clientWidth) {
metaEl.setAttribute('content', 'target-densitydpi=device-dpi,width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1');
}
function refreshRem () {
var c = '}';
var width = document.documentElement.clientWidth;
var isPhone = window.navigator.userAgent.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i);
if (!isPhone && width > 1024) {
width = 640;
c = 'max-width:' + width + 'px;margin-right:auto!important;margin-left:auto!important;}';
}
window.rem = rem = width / 16;
style.innerHTML = 'html{font-size:' + rem + 'px!important;}body{font-size:' + parseInt(12 * (width / 320)) + 'px;' + c;;
}
refreshRem();
window.addEventListener('resize', function () {
clearTimeout(timer);
timer = setTimeout(refreshRem, 300);
}, false);
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
clearTimeout(timer);
timer = setTimeout(refreshRem, 300);
}
}, false);
- vh/vw单位与 % 对比
- 百分比%是根据父元素宽度或者高度进行计算,而vw vh固定按照viewport来计算,不会受父元素宽高度影响。
- 100vw包括了页面滚动条宽度(页面滚动条属于viewport范围内,100vw当然包括了页面滚动条宽度)。但把body或者html设置为width:100%时,是不包括页面滚动条的宽度的。也就是说100vw在有纵向滚动条的情况下,会比100%宽。 那么就会引发一个问题:pc端使用vw单位时,如果有元素width:100vw,而且页面内容又超出一屏长度,出现了纵向滚动条。因为(元素100vw + 纵向滚动条宽度)超出了viewport宽度,则会导致出现横向滚动条。若页面基本上展示在移动端,那么最好用vw/vh(移动端滚动条不占位,所以不会有这个问题)。若还需要兼容pc端还是尽量使用width:100%吧。