什么是Rem
rem和em很容易混同,其实两个都是css的单位,并且也都是绝对单位,现有的em,css3才引入的rem,在介绍rem之前,咱们先来理解下em。

em作为font-size的单位时,其代表父元素的字体大小,em作为其余属性单位时,代表本身字体大小——MDN

我在面试时常常问会一道和em无关的题,来看一下面试者对css细节的理解水平,如下,问s1、s2、s5、s6的font-size和line-height别离是多少px,先来想一想,结尾处有答案和解释。
<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>

.p1 {font-size: 16px; line-height: 32px;}
.s1 {font-size: 2em;}
.s1 {font-size: 2em; line-height: 2em;}

.p2 {font-size: 16px; line-height: 2;}
.s5 {font-size: 2em;}
.s5 {font-size: 2em; line-height: 2em;}

em能够让咱们的页面更灵便,更强壮,比起到处写死的px值,em仿佛更有张力,改变父元素的字体大小,子元素会等比例变动,这一变动仿佛预示了有限可能。
有些人提出用em来做弹性布局页面,但其简单的计算让人诟病,甚至有人专门做了个px和em的计算器,不同节点像素值对应的em值,o(╯□╰)o。

em做弹性布局的毛病还在于牵一发而动全身,一旦某个节点的字体大小发生变化,那么其后辈元素都得从新计算,X﹏X。

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

rem取值分为两种状况,设置在根元素时和非根元素时,举个例子:
/ 作用于根元素,绝对于原始大小(16px),所以html的font-size为32px/
html {font-size: 2rem}

/ 作用于非根元素,绝对于根元素字体大小,所以为64px /
p {font-size: 2rem}

rem有rem的长处,em有em的长处,尺有所短,寸有所长,我始终不感觉技术没有什么对错,只有适宜不适宜,有对错的是应用技术的人,卓越与优良的区别就在于是否抉择适合的技术,并让其发挥优势。
我始终感觉em就是为字体和行高而生的,有些时候子元素字体就应该绝对于父元素,元素行高就应该绝对于字体大小;而rem的有点在于对立的参考系。
Rem布局原理
rem布局的实质是什么?这是我问过很多人的一个问题,但失去的答复都差强人意。
其实rem布局的实质是等比缩放,个别是基于宽度,试想一下如果UE图可能等比缩放,那该如许美妙啊。
假如咱们将屏幕宽度均匀分成100份,每一份的宽度用x示意,x = 屏幕宽度 / 100,如果将x作为单位,x后面的数值就代表屏幕宽度的百分比。
p {width: 50x} / 屏幕宽度的50% /

如果想要页面元素随着屏幕宽度等比变动,咱们须要下面的x单位,可怜的是css中并没有这样的单位,侥幸的是在css中有rem,通过rem这个桥梁,能够实现神奇的x
通过上面对rem的介绍,能够发现,如果子元素设置rem单位的属性,通过更改html元素的字体大小,就能够让子元素理论大小发生变化
html {font-size: 16px}
p {width: 2rem} / 32px/

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

如果让html元素字体的大小,恒等于屏幕宽度的1/100,那1rem和1x就等价了
html {fons-size: width / 100}
p {width: 50rem} / 50rem = 50x = 屏幕宽度的50% /

如何让html字体大小始终等于屏幕宽度的百分之一呢? 能够通过js来设置,个别须要在页面dom ready、resize和屏幕旋转中设置
document.documentElement.style.fontSize = document.documentElement.clientWidth / 100 + 'px';

那么如何把UE图中的获取的像素单位的值,转换为已rem为单位的值呢?公式是元素宽度 / UE图宽度 100,让咱们举个例子,假如UE图尺寸是640px,UE图中的一个元素宽度是100px,依据公式100/640100 = 15.625
p {width: 15.625rem}

上面来验证下下面的计算是否正确,上面的表格是UE图等比缩放下,元素的宽度

UE图宽度UE图中元素宽度640px100px480px75px320px50px
上面的表格是通过咱们的元素在不同屏幕宽度下的计算值

页面宽度html字体大小p元素宽度640px640/100 = 6.4px15.6256.4=100px480px480/100=4.8px15.6254.8=75px320px320/100=3.2px15.625*3.2=50px
能够发现,UE图宽度和屏幕宽度雷同时,两边得出的元素宽度是统一的
下面的计算过程有些繁琐,能够通过预处理的function来简化过程,上面是sass的例子,less相似
$ue-width: 640; / ue图的宽度 /

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

p {
width: px2rem(100);
}

下面的代码编译完的后果如下
p {width: 15.625rem}

其实有了postcss后,这个过程应该放到postcss中,源代码如下
p {width: 100px2rem}

postcss会对px2rem这个单位进行解决,解决后的后果如下,感兴趣的话来写一个px2rem的postcss插件吧
p {width: 15.625rem}

比Rem更好的计划
下面提到想让页面元素随着页面宽度变动,须要一个新的单位x,x等于屏幕宽度的百分之一,css3带来了rem的同时,也带来了vw和vh

vw —— 视口宽度的 1/100;vh —— 视口高度的 1/100 —— MDN

聪慧的你兴许一经发现,这不就是单位x吗,没错依据定义能够发现1vw=1x,有了vw咱们齐全能够绕过rem这个中介了,上面两种计划是等价的,能够看到vw比rem更简略,毕竟rem是为了实现vw么
/ rem计划 /
html {fons-size: width / 100}
p {width: 15.625rem}

/ vw计划 /
p {width: 15.625vw}

vw还能够和rem计划联合,这样计算html字体大小就不须要用js了
html {fons-size: 1vw} / 1vw = width / 100 /
p {width: 15.625rem}

尽管vw各种长处,然而vw也有毛病,首先vw的兼容性不如rem好,应用之前要看下

兼容性Ios安卓rem4.1+2.1+vw6.1+4.4+
另外,在应用弹性布局时,个别会限度最大宽度,比方在pc端查看咱们的页面,此时vw就无奈力不从心了,因为除了width有max-width,其余单位都没有,而rem能够通过管制html根元素的font-size最大值,而轻松解决这个问题
Rem不是银弹
rem是弹性布局的一种实现形式,弹性布局能够算作响应式布局的一种,但响应式布局不是弹性布局,弹性布局强调等比缩放,100%还原;响应式布局强调不同屏幕要有不同的显示,比方媒体查问

用户抉择大屏幕有两个出发点,有些人想要更大的字体,更大的图片,比方老花眼的我;有些人想要更多的内容,并不想要更大的图标。

我认为个别内容型的网站,都不太适宜应用rem,因为大屏用户能够本人抉择是要更大字体,还是要更多内容,一旦应用了rem,就剥夺了用户的自在,比方百度晓得,百度教训都没有应用rem布局;一些偏差app类的,图标类的,图片类的,比方淘宝,流动页面,比拟适宜应用rem,因为调大字体时并不能调大图标的大小
rem能够做到100%的还原度,但共事rem的制作老本也更大,同时应用rem还有一些问题,上面咱们一一列举下:
首先是字体的问题,字体大小并不能应用rem,字体的大小和字体宽度,并不成线性关系,所以字体大小不能应用rem;因为设置了根元素字体的大小,会影响所有没有设置字体大小的元素,因为字体大小是会继承的,难道要每个元素都显示设置字体大小???
咱们能够在body上做字体修改,比方把body字体大小设置为16px,但如果用户本人设置了更大的字体,此时用户的设置将生效,比方正当的形式是,将其设置为用户的默认字体大小
html {fons-size: width / 100}
body {font-size: 16px}

那字体的大小如何实现响应式呢?能够通过批改body字体的大小来实现,同时所有设置字体大小的中央都是用em单位,对就是em,因为只有em能力实现,同步变动,我早就说过em就是为字体而生的
@media screen and (min-width: 320px) {

body {font-size: 16px}

}
@media screen and (min-width: 481px) and (max-width:640px) {

body {font-size: 18px}

}
@media screen and (min-width: 641px) {

body {font-size: 20px}

}

p {font-size: 1.2em}
p a {font-size: 1.2em}

第二,如果用户在PC端浏览,页面过宽怎么办?个别咱们都会设置一个最大宽度,大于这个宽度的话页面居中,两边留白
var clientWidth = document.documentElement.clientWidth;
clientWidth = clientWidth < 780 ? clientWidth : 780;
document.documentElement.style.fontSize = clientWidth / 100 + 'px';

设置body的宽度为100rem,并程度居中
body {

margin: auto;width: 100rem

}

第三,如果用户禁用了js怎么破?其实这种用户真不多了,要不放弃吧。。。
首先能够增加noscript标签提醒用户
<noscript>开启JavaScript,取得更好的体验</noscript>

给html增加一个320时的默认字体大小,保障页面能够显示
html {fons-size: 3.2px}

如果你想要更好的体验,不如增加媒体查问吧
@media screen and (min-width: 320px) {

html {font-size: 3.2px}

}
@media screen and (min-width: 481px) and (max-width:640px) {

html {font-size: 4.8px}

}
@media screen and (min-width: 641px) {

html {font-size: 6.4px}

}

rem不是银弹,这个世上也没有银弹,每个计划都有其长处,也有其毛病,学会做出抉择和斗争