使用 CSS3 Rem 单位布局

Rem(font size of the root element)是指相对于根元素的字体大小的单位,它与 em 类似,只不过 em 是相对与父层进行计算,而 rem 是相对与根元素的 font-size 进行计算。所以它即比 px 单位灵活,又比 em 稳定,是一个很有潜力、值得尝试的 CSS 单位。

Rem 布局

简而言之就是在 CSS 布局时使用 rem 单位,上面介绍了 rem 的特点就是基于根元素的 font-size 进行计算,所以可以通过动态的修改根元素的 font-size 值大小,来让页面的布局达到自适应的等比缩放效果,从而使布局在不同尺寸的屏幕上表现一致。

适用场景

Rem 布局比较适合移动终端,因为需要兼顾的屏幕尺寸很多并且移动端的浏览器兼容性比较好。再一个就是适用于布局比例固定的设计,例如我们经常会制作类似这样的活动或产品宣传页面:

rem-1

这个页面设计元素非常多,而且还有很多的动画效果——跃出水面的鲸鱼、不断起伏的海浪、闪烁的节点等等;如果使用常规的流式布局,大屏幕会产生更多的留白,而小屏幕可能无法把设计显示完全,所以 rem 的等比缩放就非常适用。

实现

要使用 rem 单位,首先就是设置 HTML 的 font-size 值,而 font-size 的值是依照屏幕的分辨率动态设置的,这里我们以 320px 的宽度为基准,当然也可以设置 640px 为基准,可以依照自己情况而定。

设置为 320px 的原因是早期 iPhone 的分辨率为 320px × 480px,大量为 iPhone 量身定制的网站都设置了width=device-width,并且按照宽度 320px 来设计制作,所以其他浏览器加入 viewport 支持时为了兼容性也将 device-width 定义为了 320px。

那么在 320px 宽度设备下 HTML 的 font-size 就是 320 / 320 = 1px(1080px 设备下就是 1080 / 320 = 3.375),但过多的小数点位数在计算 rem 时会产生很大的误差,所以我们将值放大 10 倍(方便计算)然后再取一位小数点,即 320 / 320 * 10 = 10px(1080 / 320 * 10 = 33.7),然后可以用一段 JS 来完成这个计算:

document.documentElement.style.fontSize = (document.documentElement.clientWidth / 320 * 10).toFixed(1) + ‘px';

设置好后,320 宽度设备 HTML font-size 为 10px,即 10px = 1 rem,所以在还原设计稿时,一个 200px 的宽度元素它的 CSS 宽度就是 200 / 10 = 20 rem。这个时候我们想实现一个在所有分辨率下占屏幕一半的正方形就非常简单了:

.box{ width:50%; height:16rem;}  // 16rem = 320 / 10 * 50%

Demo:

提示:你可以先修改部分代码再运行。

可以用 Chrome 模拟各种设备尺寸来看看实际效果,最后完善下 JS 代码:

(function (doc, win) {
    var docEl = doc.documentElement;
    var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
    var recalc = function () {
        var clientWidth = docEl.clientWidth;
        if (!clientWidth) return;
        docEl.style.fontSize = (clientWidth / 320 * 10).toFixed(1) + 'px';
    };
    recalc();
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
})(document, window);

可以将这段 JS 进行压缩,放置到<head>标签内,至此 rem 布局的准备工作就完成了,剩下的就是跟平常一样还原设计稿。

局限性

Rem 并不适用于所有的页面布局,特别是文字排版,rem 的等比缩放特性会让所有设备一行显示的文字数量相同,而这时候我们更希望在大屏幕上显示更多的内容。所以在使用 rem 布局时要根据实际场景而定,大部分情况下是局部使用 rem 布局。

问题

Rem 布局使用中会遇到不少问题,这里简单做下归纳记录,持续更新

  • 对图片型的 Sprite 支持不好,建议使用 Font Icon 或者 SVG 型 Sprite;
  • 有小数点参与计算,会出现类似 50% + 50% > 100% 导致意外折行的情况;

2 comments

  1. rem的局限性这块,不适合文字排版?
    rem 的等比缩放特性会让所有设备一行显示的文字数量相同这个该怎么理解?

发表评论

电子邮件地址不会被公开。 必填项已用*标注