rem移动端相对单位

加入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*/
}

猜你喜欢

转载自blog.csdn.net/qq_42036203/article/details/88120547