简单理解网易 REM

723 阅读4分钟

rem

rem 指的是根元素的字体大小,多数根元素大小为 16px,但设备的 dpi 会影响根元素的大小,因此并不是固定的

所谓 rem 布局就是指为文档的根节点<html>元素设置一个基准字体大小,然后所有的元素尺寸都以 rem 为单位来写。

使用 rem 布局结合在 html 上根据不同分辨率设置不同 font-size 有很多不好解决的麻烦,那应该如何解决呢?我们可以通过 JS 来计算不同分辨率下,font-size 的大小,这是在我研究了网易的移动端布局之后得出的结论。

下图是网易在分辨率为 320X680,375X680,414X680,500X680 时,html 的 font-size 尺寸

比较图

它是根据什么计算的?

这就跟设计稿有关了,拿网易来说,它的设计稿应该是基于 iPhone4 或者 iPhone5 来的,所以它的设计稿竖直放时的横向分辨率为 640px,为了计算方便,取一个 100px 的 font-size 为参照,那么 body 元素的宽度就可以设置为 width: 6.4rem,于是 html 的 font-size=deviceWidth / 6.4。这个 deviceWidth 就是 viewport 设置中的那个 deviceWidth。根据这个计算规则,可得出本部分开始的四张截图中 html 的 font-size 大小如下:

deviceWidth = 320,font-size = 320 / 6.4 = 50px
deviceWidth = 375,font-size = 375 / 6.4 = 58.59375px
deviceWidth = 414,font-size = 414 / 6.4 = 64.6875px
deviceWidth = 500,font-size = 500 / 6.4 = 78.125px

这个 6.4 怎么来的?当然是根据设计稿的横向分辨率/100 得来的。

这个 deviceWidth 通过 document.documentElement.clientWidth 就能取到了,所以当页面的 dom ready 后,做的第一件事情就是:

document.documentElement.style.fontSize =
  document.documentElement.clientWidth / 6.4 + "px";

下面总结网易的这种做法:

  • 第一步移动端视口的设置:<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">

  • 第二步:

    • 先拿设计稿竖着的横向分辨率除以 100 得到 body 元素的宽度: 如果设计稿基于 iphone6,横向分辨率为 750,body 的 width 为 750 / 100 = 7.5rem 如果设计稿基于 iphone4/5,横向分辨率为 640,body 的 width 为 640 / 100 = 6.4rem
    • 布局时,设计图标注的尺寸除以 100 得到 css 中的尺寸,比如下图: 实例 播放器高度为 210px,写样式的时候 css 应该这么写:height: 2.1rem。之所以取一个 100 作为参照,就是为了这里计算 rem 的方便!
    • 在 dom ready 以后,通过以下代码设置 html 的 font-size:(6.4 只是举个例子,如果是 750 的设计稿,应该除以 7.5) document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';

另外,当 deviceWidth 大于设计稿的横向分辨率时,html 的 font-size 始终等于横向分辨率/body 元素宽: 640*680

641*680 之所以这么干,是因为当 deviceWidth 大于 640 时,则物理分辨率大于 1280(这就看设备的 devicePixelRatio 这个值了),应该去访问 pc 网站了。事实就是这样,你从手机访问网易,看到的是触屏版的页面,如果从 pad 访问,看到的就是电脑版的页面。

devicePixelRatio 属性: 该 Window 属性 devicePixelRatio 能够返回当前显示设备的物理像素分辨率与 CSS 像素分辨率的比率。

var deviceWidth = document.documentElement.clientWidth;
if (deviceWidth > 640) deviceWidth = 640;
//这里也可以改成跳转 PC 端网站
document.documentElement.style.fontSize = deviceWidth / 6.4 + "px";

最后公式

优势:不用管DPR,只需知设计稿宽度

DPR也就是设备像素比; 设备像素比(dpr) = 设备像素(分辨率)/设备独立像素(屏幕尺寸)

已知:假设现有iPhone6设计稿,宽750px,其中一元素宽150px;

根据DPR值,iPhone6的DPR值为2,我们可得其中该元素的显示尺寸:

真实显示CSS值:

公式1

现在我们用网易方案来解决这个问题:

首先我们取1rem = 100px为参考值(这个值可以随便取),可知body的宽度:

公式2

又因为body的宽度为7.5rem,由“网易公式”可得: Html的font-size为:

公式3

Dw为deviceWidth,即设备宽度,这是整个方案里唯一动态改变的值

现我们已知设计稿为iPhone6,又知iPhone6的设备宽为375px,这时候我们再回头看:html当前设备的font-size

dw计算宽度

可知,无形中这步已帮我们作了DPR换算;750px的设计稿,显示在375px的屏幕要怎样转换。前面我们取了1rem = 100px,可得该元素宽:150px = 1.5rem,又知rem为其他元素相对根元素(html)的大小,所以可得当前元素宽度的真实css显示值为:1.5rem*50px = 75px;(这里的75px就跟我们前面理想得到的75px不谋而合了)。这边我们把这个运算再拆解来看:

最总算法

学习资料 学习资料