加入QQ群:864680898,一起学习进步!点击群名可查看本人网站,有最新文章!
rem移动端相对单位
移动端禁用用户缩放
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
什么是dpr?
devicePixelRatio其实指的是window.devicePixelRatio,就是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。
一、百分比布局
为了保证在多个终端显示效果相同,宽度使用百分比
二、rem
100vw 就是100%屏幕宽度,100vh 就是100%屏幕高度,我们一般以iphone来开发,iphone6的屏幕宽度是375px,dpr为2。
我们若定义20px为1rem,那么20/375 = x/100,得 x = 5.33333333333,所以:
/* 375的设计稿,1rem为20px */
html{
font-size: 5.3333333333vw;
}
/* 750的设计稿,1rem为40px */
html{
font-size: 5.3333333333vw;
}
之后便可以直接使用rem单位,如:
/* 375的设计稿 */
html{
font-size: 5.3333333333vw;
}
.container{
width: 2rem;
height: 2rem;
}
/* 等同于 */
.container{
width: 40px;
height: 40px;
}
三、淘宝rem做法
(function(win,lib){
var doc = win.document,
docEl = doc.documentElement,
metaEl = doc.querySelector('meta[name="viewport"]'),
flexibleEl = doc.querySelector('meta[name="flexible"]'),
dpr = 0,
scale = 0,
tid,
flexible = lib.flexible || (lib.flexible = {});
if(metaEl){
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if(match){
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
}else if(flexibleEl){
var content = flexible.getAttribute('content');
if(content){
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = 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){
var isAndroid = win.navigator.appVersion.match(/android/gi),
isIphoe = win.navigator.appVersion.match(/iphone/gi),
devicePixelRatio = win.devicePixelRatio;
if(isIphoe){
if(devicePixelRatio >= 3 && (!dpr || dpr >= 3)){
dpr = 3;
}else if(devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
}else{
dpr = 1;
}
}else{
dpr = 1;
}
scale = 1 / dpr;
}
docEl.setAttribute('data-dpr',dpr);
if(!metaEl){
metaEl = doc.createElement('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.appendChild(metaEl);
}else{
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if(width / dpr > 540){
width = 540 * dpr;
}
var rem = 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){
var val = parseFloat(d) * this.rem;
if(typeof d === 'string' && d.match(/rem$/)){
val += 'px';
}
return val;
}
flexible.px2rem = function(d){
var val = parseFloat(d) * this.rem;
if(typeof d=== 'string' && d.match(/px$/)){
val += 'rem';
}
return val;
}
})(window,window['lib'] || (window['lib'] = {}));
四、网易rem做法
(function(doc,win){
var docEl = 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,
dpr = 1,
scale = 1 / dpr,
resizeEvt = 'orientationchange' in window? 'orientationchange' : 'resize';
docEl.dataset.dpr = dpr;
var metaEl = doc.createElement('meta');
metaEl.name = 'viewport';
metaEl.content = 'initial-scale=' + scale + ',minimum-scale=' + scale;
docEl.firstElementChild.appendChild(metaEl);
var recalc = function(){
var width = docEl.clientWidth;
if(width / dpr > 750){
width = 750 * dpr;
}
docEl.style.fontSize = 50 * (width / 750) + 'px';
};
recalc();
if(!doc.addEventListener){ return };
win.addEventListener(resizeEvt,recalc,false);
})(document,window);
五、px2rem插件px转rem参考文档
- 安装
npm install px2rem-loader lib-flexible –save
- 在项目入口文件main.js中引入lib-flexible
import 'lib-flexible/flexible.js'
- 在build下的 utils.js中,找到generateLoaders 方法,在这里添加
const px2remLoader = {
loader: 'px2rem-loader',
options: {
'remUnit':75,
'baseDpr':2
}
}
function generateLoaders (loader, loaderOptions) {
const loaders = [cssLoader, px2remLoader]
if (loader) {
loaders.push({
loader: loader + ‘-loader’,
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
- 配置px2rem , build目录下vue-loader.conf.js中,做如下修改:
module.exports = {
loaders: utils.cssLoaders({
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
extract: isProduction
}),
transformToRequire: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
},
postcss:[require('postcss-px2rem')({'remUnit':75,'baseDpr':2})] /*因为我是以750px(iphone6)宽度为基准,所以remUnit为75*/
}