Rem的深入理解

什么是em?

css中有两个常用的相对单位,em和rem,先有的em,css3中又引入rem,两者很容易混淆,所以在了解rem之前,需要先理清em的概念。

em作为font-size的单位时,其代表父元素的字体大小,em作为其他属性单位时,代表自身字体大小。

通过以下实例可以很清晰的解读em的内涵:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style type="text/css">
    .p1 {font-size: 16px; line-height: 32px;}
    .s1 {font-size: 2em;}
    .s2 {font-size: 2em; line-height: 2em;}

    .p2 {font-size: 16px; line-height: 2;}
    .s5 {font-size: 2em;}
    .s6 {font-size: 2em; line-height: 2em;}
</style>
<body>
    <div class="p1">
        <div class="s1">1</div>
        <div class="s2">1</div>
    </div>
    <div class="p2">
        <div class="s5">1</div>
        <div class="s6">1</div>
    </div>
</body>
</html>

在上面的实例中,在页面最终的结果
s1:font-size:32px,line-height:32px;
s2:font-size:32px,line-height:64px;
s5:font-size:32px,line-height:64px;
s6:font-size:32px,line-height:64px
通过em可以看出改动父元素的字体大小,子元素会等比例变化。em可以让页面更灵活,更健壮,比起到处写死的px值,em似乎更有张力。
基于em的这一特点,理论上是可以用em来做弹性布局页面,但其复杂的计算让人诟病,有人专门做了个px和em的转换表,不同节点像素值对应的em值,如下:


px和em的转换表

更重要的问题在于如果rem做弹性布局的缺点,牵一发而动全身,一旦某个节点的字体大小发生变化,那么其后代元素都需要重新计算,这样带来的工作量无疑是繁琐的。

对rem的理解

rem作用于非根元素时,相对于根元素字体大小;rem作用于根元素字体大小时,相对于其出初始字体大小。

rem取值分为两种情况,设置在根元素时和非根元素时

/* 作用于根元素,相对于原始大小(16px),所以html的font-size为32px*/
html {font-size: 2rem}

/* 作用于非根元素,相对于根元素字体大小,这里的根元素的字体大小为32px,所以p标签的字体大小为64px */
p {font-size: 2rem}

em和rem各有优点
对于em来说,可以认为em是为字体和行高而生的,有些时候子元素字体就应该相对于父元素,元素行高就应该相对于字体大小。
对于rem来说,可以基于rem来建立一个同一参考系的概念。

Rem布局原理

rem布局的本质是等比缩放,一般是基于宽度。
想象将屏幕宽度平均分成100份,每一份的宽度用x表示,x = 屏幕宽度 / 100,如果将x作为单位,x前面的数值就代表屏幕宽度的百分比,一个元素宽度为50x,那么该元素实际就占到了屏幕宽度的一半。基于这个理念,在css中,可以通过rem这个桥梁,实现页面元素随着屏幕宽度来进行等比变化。

html {font-size: 16px}
p {width: 2rem} /* 32px*/

html {font-size: 32px}
p {width: 2rem} /*64px*/

如上,如果子元素设置rem单位的属性,通过更改html元素的字体大小,就可以让子元素实际大小发生变化。
如果让html元素字体的大小,恒等于屏幕宽度的1/100,那么计算起来会更方便一些,比如此时html根元素大小为75,页面一个元素的10rem,那么该元素的实际宽度就是75*10=750px;
通常通过js让html根元素字体大小一直等于屏幕宽度的百分之一,一般需要在页面dom ready、resize和屏幕旋转中设置

document.documentElement.style.fontSize = document.documentElement.clientWidth / 100 + 'px';

如何把设计稿图中的元素像素单位的值,转换为已rem为单位的值?

假设设计图宽度为a,根元素大小为f,将来设计图是要完全铺满页面的,那么根据以上,可以得知 f=a/100;
假设设计稿有一个元素的像素宽度为b,其对应的rem的值为R,那么存在以下关系:
b=Rf=R(a/100)=>R=b/(a/100)=(b/a)100
元素的rem的值 = 元素宽度 / UE图宽度 * 100
假设UE图尺寸是640px,UE图中的一个元素宽度是100px,根据公式100/640
100 = 15.625,元素的宽度为15.625rem。
可以通过以下的图标来验证上面的论述是正确的。


UE图宽度和屏幕宽度相同时,可以看出两边得出的元素宽度是一致的。

所以,在使用rem原理来布局的话,根据实际元素的像素,计算出对应的rem值,就可以做到页面的伸缩布局布局了。

但是,如果每个元素的宽高,以及位置,从像素单位转化为对应的rem值时,都需要计算,又会显得很繁琐,这里可以借用其他的方式实现免掉计算这一过程,布局时直接写px,后期页面渲染时通过某种方式来直接将px转化为rem。

1、 可以通过预处理的function来简化过程,比如使用sass

$ue-width: 640; /* ue图的宽度 */

@function px2rem($px) {
  @return #{$px/$ue-width*100}rem;
}

p {
  width: px2rem(100);
}

上面的代码编译完的结果如下

p {width: 15.625rem}

2、使用相关插件cssrem,将CSS的 px 值直接转为 rem 值

效果如下


cssrem
在sublime中安装和配置cssrem插件的详情参照如下:

安装

  • 下载本项目,比如:git clone https://github.com/flashlizi/cssrem
  • 进入packages目录:Sublime Text -> Preferences -> Browse Packages...
  • 复制下载的cssrem目录到刚才的packges目录里。
  • 重启Sublime Text。

配置参数

参数配置文件:Sublime Text -> Preferences -> Package Settings -> cssrem

  • px_to_rem - px转rem的单位比例,默认为40。
  • max_rem_fraction_length - px转rem的小数部分的最大长度。默认为6。
  • available_file_types - 启用此插件的文件类型。默认为:[".css", ".less", ".sass"]。

VScode cssrem插件使用 详细教程

3、 此外还可以使用postcss来处理

p {width: 100px2rem}

postcss会对px2rem这个单位进行处理,处理后的结果如下

p {width: 15.625rem}

可参考:
postcss-pxtorem:移动端px自动转为rem

可参考的其他相关内容:

1、 从网易与淘宝的font-size思考前端设计稿与工作流

2、高清显示屏原理以及设计方案

3、移动web适配之rem

4、设备像素比devicePixelRatio简单介绍

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容