移动端rem适配

242 阅读4分钟
在不同的屏幕上,CSS像素所呈现的物理尺寸是一致的,而不同的是CSS像素所对应的物理像素具数是不一致的。在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素。

物理像素

设备屏幕实际拥有的像素点,屏幕的基本单元,是有实体的。比如iPhone 6的屏幕在宽度方向有750个像素点,高度方向有1334个像素点,所有iPhone 6 总共有750*1334个像素点。

逻辑像素

也叫“设备独立像素”(Device Independent Pixel,DIP),可以理解为反映在CSS/JS程序里面的像素点,也就是说css像素是逻辑像素的一种。

设备像素比(Device Pixel Ratio,DPR)

设备的物理像素与逻辑像素之比。 dpr的全称是window.devicePixelRatio,它等于物理像素 / dips。其实就是一个比例。(物理像素就是一个个的小格子,用来显示不同颜色的。dips可以理解为虚拟像素,就像我们写的css.当dpr=2时,设备像素数为640 x 1136px,而CSS逻辑像素数为320 x 568px。

设备独立像素

不同分辨率的手机,它们在界面上显示元素的大小是多少。一个设备独立像素里可能包含1个或者多个物理像素点,包含的越多则屏幕看起来越清晰。chrome检查元素模拟调试手机设备时显示如375x667和 320x480都是设备独立像素。

viewport

视口(viewport)代表当前可见的计算机图形区域。通常与浏览器窗口相同,但不包括浏览器的UI, 菜单栏等——即指你正在浏览的文档的那一部分。

布局视窗

布局视口是网页布局的基准窗口,在PC浏览器上,布局视口就等于当前浏览器的窗口大小(不包括borders 、margins、滚动条)。在移动端不设置视窗宽度时,页面宽度默认为 980px,页面可以左右滚动。

获取布局视口大小:document.documentElement.clientWidth / clientHeight image.png

视觉视窗

用户通过屏幕真实看到的区域视觉视口默认等于当前浏览器的窗口大小(包括滚动条宽度)。 可以简单理解为手持设备物理屏幕的可视区域。也就是你的手机屏幕,所以不同设备的视觉视口可能不同 获取视觉视口大小:window.innerWidth / innerHeight

image.png

理想视窗

布局视口宽度 =理想视口宽度 = 视觉视口宽度。要设置content="width=device-width;".

获取理想视窗大小:window.width / height

image.png

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">

规定了我们的视口宽度为屏幕宽度,不能进行缩放,初始缩放比例为1,就是初始时候我们的视觉视口就是理想视口。 image.png

适配方案

rem

(function (doc, win) {
      var docEl = doc.documentElement,
      resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
      recalc = function () {
      //如果布局视口大于750就设置750
        const clientWidth = docEl.clientWidth > 750 ? 750 : docEl.clientWidth;
        if (!clientWidth) return;
        if (clientWidth === 750) {
          docEl.style.fontSize = '16px';
          return
        };
        //750px的设计稿 1rem = 100px;
        //公式:750/clientWidth = 100/fontSize
        docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'; // 750设计稿
      };
      if (!doc.addEventListener) return;
      win.addEventListener(resizeEvt, recalc, false);
      doc.addEventListener('DOMContentLoaded', recalc, false);
    })(document, window);

设计稿为750px,为了好计算,我们设置1rem = 100px。而750/clientWidth = 100/fontSize,就可以算出fontSize。所以设计稿每个元素的宽高除以100,就是对于的移动端的rem.

postcss-pxtorem

使用一 index.html

(function (doc, win) {
      var docEl = doc.documentElement,
      resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
      recalc = function () {
      //如果布局视口大于750就设置750
        const clientWidth = docEl.clientWidth > 750 ? 750 : docEl.clientWidth;
        if (!clientWidth) return;
        if (clientWidth === 750) {
          docEl.style.fontSize = '16px';
          return
        };
        //750px的设计稿 1rem = 100px;
        //公式:750/clientWidth = 100/fontSize
        docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'; // 750设计稿
      };
      if (!doc.addEventListener) return;
      win.addEventListener(resizeEvt, recalc, false);
      doc.addEventListener('DOMContentLoaded', recalc, false);
    })(document, window);

postcss.config.js

  plugins: {
    autoprefixer: {},
    'postcss-pxtorem': {
      rootValue:100,//根元素的值,即1rem的值
      minPixelValue: 2,
      propList: ['*'],
    }
  }
}


使用:设计稿上面的宽度为750px,直接width:750px;设计稿宽度为375px,直接width:375px。

页面渲染为:width:7.5rem

若无配置postcss.config.js,则 设计稿上面的宽度为750px,编写css为width:7.5rem

所以上面的postcss-pxtorem配置的作用就是:将页面中的px/100转化为rem。

设置根元素为百分比

html的font-size默认是16px => 1rem=16px;chrome最小的像素是12px,为了兼容性和好计算,设置1rem = 100px = 16px * 625%。所以我们会看到根元素的font-size设置为625%,设置这个就代表了1rem = 100px。

这样,14px =( 14/100 )rem = 0.14rem。