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 元素宽:
之所以这么干,是因为当 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值:
现在我们用网易方案来解决这个问题:
首先我们取1rem = 100px为参考值(这个值可以随便取),可知body的宽度:
又因为body的宽度为7.5rem,由“网易公式”可得: Html的font-size为:
Dw为deviceWidth,即设备宽度,这是整个方案里唯一动态改变的值。
现我们已知设计稿为iPhone6,又知iPhone6的设备宽为375px,这时候我们再回头看:html当前设备的font-size:
可知,无形中这步已帮我们作了DPR换算;750px的设计稿,显示在375px的屏幕要怎样转换。前面我们取了1rem = 100px,可得该元素宽:150px = 1.5rem,又知rem为其他元素相对根元素(html)的大小,所以可得当前元素宽度的真实css显示值为:1.5rem*50px = 75px;(这里的75px就跟我们前面理想得到的75px不谋而合了)。这边我们把这个运算再拆解来看: