什么是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值,如下:
更重要的问题在于如果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/640100 = 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 值
效果如下
在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"]。
3、 此外还可以使用postcss来处理
p {width: 100px2rem}
postcss会对px2rem这个单位进行处理,处理后的结果如下
p {width: 15.625rem}
可参考:
postcss-pxtorem:移动端px自动转为rem
可参考的其他相关内容: