关于rem布局

前言

由于移动端的设备存在许多分辨率的差异,所以一般的面向移动端的网站都不会直接按照某一固定分辨率的屏幕进行设计,而是尽可能的适配所有分辨率的移动端设备。除了响应式布局之外,最近听闻基于rem的等比例适配布局比较流行。还有就是最近面试的时候连续被问到rem是什么,我竟哑口无言,简直惭愧,看来对于移动端这一块了解的确实是太少了,得好好补一补。

等比例适配布局

等比例,顾名思义就是尽管随着设备屏幕分辨率大小的不同页面元素的大小也不同,但是所有分辨率下展示的页面元素之间宽度的比例关系没有发生改变;比如:在一个设备宽度为480px的屏幕下,a元素的宽度为480pxb元素的宽度为240px,而在另一个设备宽度为320px的屏幕下,a元素的宽度为320pxb元素的宽度为160px,这样a元素与b元素之间宽度大小的比例没有变化,且正比于设备宽度

相关概念

  1. 物理像素

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

  1. 设备独立像素density-independent pixel):

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css 像素),然后由相关系统转换为物理像素。

  1. 屏幕分辨率:也叫物理像素分辨率,即显示器拥有的物理像素的个数。比如:1080x1920表示该显示器的水平方向有1080个物理像素,而竖直方向有1920个物理像素;

  2. 设备独立分辨率:即显示器拥有的设备独立像素的个数(水平,竖直方向)。由于css中的像素为设备独立像素,所以获取的元素的宽高使用的像素也是设备独立像素,比如window.innerWidth实际上获取的是视窗的设备独立像素宽度,而非物理像素的宽度!

  3. 设备像素比device pixel ratio):简称dpr

1
设备像素比 = 物理像素个数 / 设备独立像素个数 (水平或竖直方向)

比如:某手机的屏幕分辨率为1080x1920,而其设备独立分辨率为360x640,因此该手机的dpr = 3dpr = 3的意思就是css中设置的1px实际上对应了3 * 3个物理像素!

mark

  1. 位图像素

一个位图像素是栅格图像(如:png, jpg, gif 等)最小的数据单元。每一个位图像素都包含着一些自身的显示信息(如:显示位置,颜色值,透明度等)。

rem

remcss3新增的一种相对单位,即root em;而1 em指的就是当前元素font-size值,因此1 rem就指的是根元素htmlfont-size值。比如:html元素的font-size: 16px;,那么1 rem就等于16px,同理0.5 rem就是8px

rem与等比例适配布局

由于rem针对的是html元素,那么只需要将html元素的font-size与设备屏幕的宽度进行正相关,然后其他页面都使用rem来设置宽度,那么就能很轻易地实现不同大小设备之间的等比例适配布局。

1
2
3
4
5
6
7
/**
* 用来根据当前设备宽度来调整html元素的font-size
* @param n: 默认设计稿宽度对应的rem数,即设备宽度被分割成个rem
*/
function rem(n = 10){
document.documentElement.style.fontSize = document.documentElement.clientWidth / n + 'px'
}

一些问题

移动端兼容性

由于移动端(主要是安卓)的浏览器app数量众多,内核又各不相同,因此多少会出现一些意料之外的事情;

目前我发现的兼容性问题主要是某些浏览器对于所有元素的最小font-size值有限制(比如夸克浏览器设置的最小font-size值为8px),当html设置的font-size小于浏览器的最小值时,浏览器默认会使用font-size最小值进行替换,因此会造成其它依赖rem的元素完全变样;除此之外,某些浏览器还有小数点精度的问题,即当设置的font-size值过小,而其它元素的rem值比较大时,小数点后的精度就变得十分敏感了,因此会出现元素尺寸与设计图相差一定px的情况(小米自带浏览器就会出现,当font-size小于1px时,有些元素的尺寸就会出现偏差);

因此,最好将htmlfont-size设置比较大一点;比如可以将设备宽度划分为10rem,使得htmlfont-size值在不同分辨率的设备之间都保持在一个较大的数字,然后利用scss自动计算元素的rem值即可。

图片模糊

由于<img>元素是位图,因此如果设备的dpr > 1时且设计图的尺寸是按照一倍屏(dpr = 1)进行设计时,图片中一个像素点信息要分到设备中的多个像素点,就相当于把图片放大了;一般图片放大都是利用临近插值算法模拟多余的像素点信息,所以图片自然就模糊了。

解决的办法就是按照二倍屏(dpr = 2)进行设计,因此图片资源尺寸被放大了一倍,在一倍屏和二倍屏上显示自然不会有模糊问题;还有一种办法就是准备多种尺寸的图片资源,利用js检测设备的dpr,然后选择使用对应尺寸的图片。

参考文档

  1. rem布局解析 - 掘金
  2. 《css世界》 —— 8.1.2 理解 font-sizeexemrem 的关系
  3. 【原创】移动端高清、多屏适配方案 - 移动端H5 - 前端乱炖