移动端rem自适应方案
假设设计妹妹给我们的设计稿尺寸为750 * 1340。结合网易、淘宝移动端首页html元素上的font-size属性,html5设计稿尺寸以及前端与设计之间协作流程一般分为下面两种。
一、网易做法
引入:页面开头处引入下面这段代码,用于动态计算font-size
-
(function(doc, win) {
-
vardocEl = doc.documentElement,
-
isIOS = navigator.userAgent.match(/(i[^;]+;( U;)? CPU.+Mac OS X/),
-
dpr = isIOS ? Math.min(win.devicePixelRatio, 3) : 1,
-
dpr = window.top === window.self? dpr : 1, //被iframe引用时,禁止缩放
-
dpr = 1,
-
scale = 1/ dpr,
-
resizeEvt = 'orientationchange'inwindow ? 'orientationchange': 'resize';
-
docEl.dataset.dpr = dpr;
-
varmetaEl = doc.('meta');
-
metaEl.name = 'viewport';
-
metaEl.content = 'initial-scale='+ scale + ',maximum-scale='+ scale + ', minimum-scale='+ scale;
-
docEl.firstElementChild.(metaEl);
-
varrecalc = function() {
-
varwidth = docEl.clientWidth;
-
if(width / dpr > 750) {
-
width = 750* dpr;
-
}
-
// 乘以100,px : rem = 100 : 1
-
docEl.style.fontSize = 100* (width / 750) + 'px';
-
};
-
recalc()
-
if(!doc.addEventListener) return;
-
win.addEventListener(resizeEvt, recalc, false);
-
})(document, window);
使用:
未引入前
-
body {
-
width: 750px;
-
height: 640px;
-
}
引入后:除以100并将px换成rem
-
body {
-
width: 7.5rem;
-
height: 6.4rem;
-
}
换算的依据:
-
// 乘以100,px : rem = 100 : 1
-
varrecalc = function() {
-
varwidth = docEl.clientWidth;
-
if(width / dpr > 750) {
-
width = 750* dpr;
-
}
-
// 乘以100,px : rem = 100 : 1
-
docEl.style.fontSize = 100* (width / 750) + 'px';
-
};
引入:页面开头处引入下面这段代码,用于动态计算font-size,或者单独放入一个文件,引入文件也可以
-
;
-
(function(win, lib) {
-
vardoc = win.document;
-
vardocEl = doc.documentElement;
-
varmetaEl = doc.querySelector('meta[name="viewport"]');
-
varflexibleEl = doc.querySelector('meta[name="flexible"]');
-
vardpr = 0;
-
varscale = 0;
-
vartid;
-
varflexible = lib.flexible || (lib.flexible = {});
-
if(metaEl) {
-
varmatch = metaEl.getAttribute('content').match(/initial-scale=([d.]+)/);
-
if(match) {
-
scale = parseFloat(match[1]);
-
dpr = parseInt(1/ scale);
-
}
-
} elseif(flexibleEl) {
-
varcontent = flexibleEl.getAttribute('content');
-
if(content) {
-
varinitialDpr = content.match(/initial-dpr=([d.]+)/);
-
varmaximumDpr = content.match(/maximum-dpr=([d.]+)/);
-
if(initialDpr) {
-
dpr = parseFloat(initialDpr[1]);
-
scale = parseFloat((1/ dpr).toFixed(2));
-
}
-
if(maximumDpr) {
-
dpr = parseFloat(maximumDpr[1]);
-
scale = parseFloat((1/ dpr).toFixed(2));
-
}
-
}
-
}
-
if(!dpr && !scale) {
-
varisAndroid = win.navigator.appVersion.match(/android/gi);
-
varisIPhone = win.navigator.appVersion.match(/iphone/gi);
-
vardevicePixelRatio = win.devicePixelRatio;
-
if(isIPhone) {
-
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
-
if(devicePixelRatio >= 3&& (!dpr || dpr >= 3)) {
-
dpr = 3;
-
} elseif(devicePixelRatio >= 2&& (!dpr || dpr >= 2)) {
-
dpr = 2;
-
} else{
-
dpr = 1;
-
}
-
} else{
-
// 其他设备下,仍旧使用1倍的方案
-
dpr = 1;
-
}
-
scale = 1/ dpr;
-
}
-
docEl.setAttribute('data-dpr', dpr);
-
if(!metaEl) {
-
metaEl = doc.('meta');
-
metaEl.setAttribute('name', 'viewport');
-
metaEl.setAttribute('content', 'initial-scale='+ scale + ', maximum-scale='+ scale + ', minimum-scale='+ scale + ', user-scalable=no');
-
if(docEl.firstElementChild) {
-
docEl.firstElementChild.(metaEl);
-
} else{
-
varwrap = doc.('p');
-
wrap.(metaEl);
-
doc.write(wrap.innerHTML);
-
}
-
}
-
functionrefreshRem() {
-
varwidth = docEl.getBoundingClientRect().width;
-
// 适配平板
-
if(width / dpr > 540) {
-
width = 540* dpr;
-
}
-
varrem = width / 10;
-
docEl.style.fontSize = rem + 'px';
-
flexible.rem = win.rem = rem;
-
}
-
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);
-
if(doc.readyState === 'complete') {
-
doc.body.style.fontSize = 12* dpr + 'px';
-
} else{
-
doc.addEventListener('DOMContentLoaded', function(e) {
-
doc.body.style.fontSize = 12* dpr + 'px';
-
}, false);
-
}
-
refreshRem();
-
flexible.dpr = win.dpr = dpr;
-
flexible.refreshRem = refreshRem;
-
flexible.rem2px = function(d) {
-
varval = parseFloat(d) * this.rem;
-
if(typeofd === 'string'&& d.match(/rem$/)) {
-
val += 'px';
-
}
-
returnval;
-
}
-
flexible.px2rem = function(d) {
-
varval = parseFloat(d) / this.rem;
-
if(typeofd === 'string'&& d.match(/px$/)) {
-
val += 'rem';
-
}
-
returnval;
-
}
-
})(window, window['lib'] || (window['lib'] = {}));
使用:
未引入前
-
body {
-
width: 750px;
-
height: 640px;
-
}
引入后
-
@font-size-base: 75;
-
body {
-
width: 750rem/@font-size-base;
-
height: 640rem/@font-size-base;
-
}
换算依据:
-
functionrefreshRem() {
-
varwidth = docEl.getBoundingClientRect().width;
-
// 适配平板
-
if(width / dpr > 540) {
-
width = 540* dpr;
-
}
-
varrem = width / 10;
-
docEl.style.fontSize = rem + 'px';
-
flexible.rem = win.rem = rem;
-
}
这边是用的less,如果您没有用less,就需要手动计算,当然也可以转化为px : rem = 100 : 1。如果想转化为px : rem = 100 : 1,可以修改上面的refreshRem函数:
-
functionrefreshRem() {
-
varwidth = docEl.getBoundingClientRect().width
-
// 适配平板
-
if(width / dpr > 750) {
-
width = 750* dpr
-
}
-
varrem = 100* (width / 750)
-
docEl.style.fontSize = rem + 'px'
-
flexible.rem = win.rem = rem;
-
}
使用:
未引入前
-
body {
-
width: 750px;
-
height: 640px;
-
}
引入后:除以100并将px换成rem
-
body {
-
width: 7.5rem;
-
height: 6.4rem;
-
}
换算依据就是上面修改的代码:
-
functionrefreshRem() {
-
varwidth = docEl.getBoundingClientRect().width
-
// 适配平板
-
if(width / dpr > 750) {
-
width = 750* dpr
-
}
-
varrem = 100* (width / 750)
-
docEl.style.fontSize = rem + 'px'
-
flexible.rem = win.rem = rem;
-
}
希望对需要的朋友有所帮助!