什么是em?
css中有兩個常用的相對單位,em和rem,先有的em,css3中又引入rem,兩者很容易混淆,所以在了解rem之前,需要先理清em的概念。
em作為font-size的單位時,其代表父元素的字體大小,em作為其他屬性單位時,代表自身字體大小。
通過以下實例可以很清晰的解讀em的內(nèi)涵:
<!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>
在上面的實例中,在頁面最終的結(jié)果
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來做彈性布局頁面,但其復(fù)雜的計算讓人詬病,有人專門做了個px和em的轉(zhuǎn)換表,不同節(jié)點像素值對應(yīng)的em值,如下:

更重要的問題在于如果rem做彈性布局的缺點,牽一發(fā)而動全身,一旦某個節(jié)點的字體大小發(fā)生變化,那么其后代元素都需要重新計算,這樣帶來的工作量無疑是繁瑣的。
對rem的理解
rem作用于非根元素時,相對于根元素字體大?。籸em作用于根元素字體大小時,相對于其出初始字體大小。
rem取值分為兩種情況,設(shè)置在根元素時和非根元素時
/* 作用于根元素,相對于原始大?。?6px),所以html的font-size為32px*/
html {font-size: 2rem}
/* 作用于非根元素,相對于根元素字體大小,這里的根元素的字體大小為32px,所以p標(biāo)簽的字體大小為64px */
p {font-size: 2rem}
em和rem各有優(yōu)點
對于em來說,可以認(rèn)為em是為字體和行高而生的,有些時候子元素字體就應(yīng)該相對于父元素,元素行高就應(yīng)該相對于字體大小。
對于rem來說,可以基于rem來建立一個同一參考系的概念。
Rem布局原理
rem布局的本質(zhì)是等比縮放,一般是基于寬度。
想象將屏幕寬度平均分成100份,每一份的寬度用x表示,x = 屏幕寬度 / 100,如果將x作為單位,x前面的數(shù)值就代表屏幕寬度的百分比,一個元素寬度為50x,那么該元素實際就占到了屏幕寬度的一半。基于這個理念,在css中,可以通過rem這個橋梁,實現(xiàn)頁面元素隨著屏幕寬度來進(jìn)行等比變化。
html {font-size: 16px}
p {width: 2rem} /* 32px*/
html {font-size: 32px}
p {width: 2rem} /*64px*/
如上,如果子元素設(shè)置rem單位的屬性,通過更改html元素的字體大小,就可以讓子元素實際大小發(fā)生變化。
如果讓html元素字體的大小,恒等于屏幕寬度的1/100,那么計算起來會更方便一些,比如此時html根元素大小為75,頁面一個元素的10rem,那么該元素的實際寬度就是75*10=750px;
通常通過js讓html根元素字體大小一直等于屏幕寬度的百分之一,一般需要在頁面dom ready、resize和屏幕旋轉(zhuǎn)中設(shè)置
document.documentElement.style.fontSize = document.documentElement.clientWidth / 100 + 'px';
如何把設(shè)計稿圖中的元素像素單位的值,轉(zhuǎn)換為已rem為單位的值?
假設(shè)設(shè)計圖寬度為a,根元素大小為f,將來設(shè)計圖是要完全鋪滿頁面的,那么根據(jù)以上,可以得知 f=a/100;
假設(shè)設(shè)計稿有一個元素的像素寬度為b,其對應(yīng)的rem的值為R,那么存在以下關(guān)系:
b=Rf=R(a/100)=>R=b/(a/100)=(b/a)100
元素的rem的值 = 元素寬度 / UE圖寬度 * 100
假設(shè)UE圖尺寸是640px,UE圖中的一個元素寬度是100px,根據(jù)公式100/640100 = 15.625,元素的寬度為15.625rem。
可以通過以下的圖標(biāo)來驗證上面的論述是正確的。

UE圖寬度和屏幕寬度相同時,可以看出兩邊得出的元素寬度是一致的。
所以,在使用rem原理來布局的話,根據(jù)實際元素的像素,計算出對應(yīng)的rem值,就可以做到頁面的伸縮布局布局了。
但是,如果每個元素的寬高,以及位置,從像素單位轉(zhuǎn)化為對應(yīng)的rem值時,都需要計算,又會顯得很繁瑣,這里可以借用其他的方式實現(xiàn)免掉計算這一過程,布局時直接寫px,后期頁面渲染時通過某種方式來直接將px轉(zhuǎn)化為rem。
1、 可以通過預(yù)處理的function來簡化過程,比如使用sass
$ue-width: 640; /* ue圖的寬度 */
@function px2rem($px) {
@return #{$px/$ue-width*100}rem;
}
p {
width: px2rem(100);
}
上面的代碼編譯完的結(jié)果如下
p {width: 15.625rem}
2、使用相關(guān)插件cssrem,將CSS的 px 值直接轉(zhuǎn)為 rem 值
效果如下

在sublime中安裝和配置cssrem插件的詳情參照如下:
安裝
- 下載本項目,比如:git clone https://github.com/flashlizi/cssrem
- 進(jìn)入packages目錄:Sublime Text -> Preferences -> Browse Packages...
- 復(fù)制下載的cssrem目錄到剛才的packges目錄里。
- 重啟Sublime Text。
配置參數(shù)
參數(shù)配置文件:Sublime Text -> Preferences -> Package Settings -> cssrem
- px_to_rem - px轉(zhuǎn)rem的單位比例,默認(rèn)為40。
- max_rem_fraction_length - px轉(zhuǎn)rem的小數(shù)部分的最大長度。默認(rèn)為6。
- available_file_types - 啟用此插件的文件類型。默認(rèn)為:[".css", ".less", ".sass"]。
3、 此外還可以使用postcss來處理
p {width: 100px2rem}
postcss會對px2rem這個單位進(jìn)行處理,處理后的結(jié)果如下
p {width: 15.625rem}
可參考:
postcss-pxtorem:移動端px自動轉(zhuǎn)為rem
可參考的其他相關(guān)內(nèi)容: