談一談rem的應用場景及其如何使用

rem

rem是什麼

相信大多數同學都寫過移動端,那麼對rem就很熟悉了,它是相對長度單位。相對於根元素(即html元素)font-size計算值的倍數的一個css單位,也就是我們
前端常說的適配單位rem。


認識rem

當瀏覽器解析HTML文檔時,創建了一個用來代表頁面元素的集合,叫做DOM(文檔對象模型,Document Object Model)。樹狀結構,每一個節點代表一個元素。<html>就是頂層節點(根節點),在下面的是它的子節點<head>和<body>,再往下就是它們的子節點,還有後代節點,如此類推。

根節點是文檔裏所有其他元素的祖先。它有一個特別的僞類(pseudo-class)選擇器(:root),在樣式表裏可以用這個選擇器表示。使用帶類名的類型選擇器html,或者直接用標籤選擇器,效果是一樣的。

rem是根em(root em)的縮寫。rem是和根元素關聯的,不依賴當前元素。不管你在文檔中的什麼地方使用這個單位,1.2rem的計算值是相等的,等於1.2倍的根元素的字號大小。

這樣前後鋪墊相信童鞋們可以理解它。


對font-size使用rem

 

:root{                       1
   font-size: 1em;           2
}
ul{
   font-size: 1rem;
}
  • 1 僞類:root等價於css的html選擇器;
  • 2 使用了瀏覽器標準字號(16px);

在這個示例裏,根字號大小是瀏覽器的默認大小16px(根元素的1em等於瀏覽器的默認字號大小)。無序列表的字號大小爲0.8rem,計算結果是12.8px。因爲這隻跟根元素相關,儘管你在列表裏嵌套了列表,嵌套子列表的字號仍然保持不變。

可用性:對font-size使用相對長度單位

一些瀏覽器會提供給用戶2種方式定製文字的大小:縮放和設置一個默認的字號大小。通過按Ctrl+或者Ctrl-,用戶可以對頁面進行縮放。這在視覺上會把整個頁面的文字或圖片(其實是所有元素)都放大或縮小了。在一些瀏覽器,這個改變只針對當前的標籤頁且是臨時的,不會影響到新開的標籤頁。

設置默認字號大小,會有點不一樣。不僅僅是設置的入口比較難找(一般在瀏覽器的設置頁),而且這個設置是永久的,直到用戶把默認值還原。值得注意的是,這個設置對使用px或其他絕對單位定義的字號大小無效。因爲默認字號大小對一些用戶是必要的,尤其是弱視的羣體,你應該用相對單位或百分比來定義字號的大小。

深度瞭解rem

rem簡化了很多em帶來的複雜度。事實上,rem提供了一個在px和em間的相對單位折中解決方案,而且更易於使用。那麼,是不是意味着你應該在對所有元素都使用rem,去掉其他長度單位呢?當然不是。

在CSS的世界裏,這個答案通常是,看情況。rem只是你的工具箱中的其中一個。掌握CSS很重要的一點,就是學會分辨在什麼場景下該使用什麼工具。我的選擇是,對font-size使用rem,對border使用px,對其他的度量方式如padding、margin、border-radius等使用em。然而在必要時,需要聲明容器的寬度的話,我更喜歡使用百分比。

這樣,字號大小就變得可預測,而當其他因素影響到元素的字號大小時,你也可以藉助em去縮放元素的padding和margin。在border上使用像素是很合適的,尤其當你想要一根漂亮的線的時候。以上就是我對不同屬性使用不同單位的理想方案,不過我要再次聲明,這些都是工具,在某些特定場景下,利用不同的工具可能取到更好的效果。
提示:在你不確定的時候字號給rem,border給px,其他單位值給em

請停止使用像素思維去思考

把頁面的根元素字號大小定義爲0.625em或者62.5%,在最近幾年來,這樣的用法很常見,這是一種模式,或者更貼切地說,這是一種反模式。
[ 下面代碼全局定義font-size爲10px ]

 

html{
    font-size: .625em;
}

我並不推薦這種用法。這個用法把瀏覽器默認的字號大小16px縮小到10px。這樣做的好處是簡化了計算,如果設計師告訴你字號大小應該是14px,那你可以很輕易地計算出1.4rem,畢竟我們還是在使用相對單位。

一開始,這看起來很方便,但事實上這樣的實現方式有兩個問題。第一,強制你寫了很多重複的樣式代碼。10px對於大多數文本來說太小了,你需要在整個頁面中,來來回回地覆蓋它。你會發現,自己把一段段落(<p>)的字號大小聲明爲1.4rem,然後又把導航(<nav>)的鏈接字號大小聲明爲1.4rem,樣式代碼中還有很多這樣的用法。這樣引入了更高的錯誤風險,當你需要修改時發現代碼耦合程度比較高,同時也會讓樣式文件變大。

第二個問題是,你這麼做的時候,其實你還是在用像素的思維在思考。雖然在代碼裏寫的是1.4rem,但是在你的腦子裏,其實還是想的是14px,哈哈,我以前一直這樣。在響應式網頁開發中,我們應該學會適應那些“模糊”的值。1.2em實際等於多少像素,並不重要,你只需要知道這是比繼承的字號大一點點,那就足夠了。而且,如果在屏幕上這不是你想要的效果,那就改吧。這是需要時間實驗和試錯的,但事實上,使用px的時候我們也需要這樣做。

當使用em時,我們很容易陷入糾結,這個值轉化成像素值會是多少呢?尤其對於字號大小。你一直在乘和除以em值,這樣你很快就會瘋掉了。相反,我希望你可以接受一項挑戰,嘗試培養先開始使用em的習慣。如果你習慣使用像素,那轉成em是需要一定時間和練習的,但相信我,這很值得。

這不是在說你再也不使用像素了。如果你跟一個設計師合作,你可能需要用更精確的像素值去溝通,這沒問題的。在項目的開始,你需要聲明一個基礎的字號大小(通常是對標題或者標註的常用字號)。使用絕對值去描述大小,往往會更加容易。

轉換成rem會有計算環節,那就讓計算器去忙吧(通常我會在Mac電腦上按cmd+空格,在Spotlight裏計算)。首先在根元素上聲明根字號大小,從那開始,使用像素應該是例外的情況,而不是常態。

在這章內容裏,我還是會持續地聊起像素。這會有助於我解釋相對單位的工作原理,同時也能幫助你培養計算em值的習慣。在這章之後,我基本會使用相對單位來討論字號的大小。

設置一個合理在字號大小

先假設你想把默認字號設定爲14px。把10px設定爲基準值,再在頁面中去覆蓋它的寫法,我們不推薦這種寫法,相反,你應該在根元素上直接聲明一個值。
在這個代碼片段裏,目標字號值是繼承的,瀏覽器的默認值16px,那麼14/16 = 0.875。

把下面的代碼添加到一個新的樣式表的最上面,我們會在這上面添加其他代碼。這裏設定根元素(<html>)的默認字號大小。

 

:root:{                      1
     font-size:0.87em;       2
}
  • 1 或者使用 HTML 選擇器;
  • 2 14/16(期望值px / 繼承值px)等於0.875;

現在,你的期望基準字號14px對整個頁面的元素有效,你不需要在其他地方重新聲明瞭。你只需要在設計不一樣的地方修改成新的字號,譬如標題。

創建的這個面板,基於14px字號,使用相對單位。

摸版

代碼實例

 

<div class="panel">
    <h2>Single-origin</h2>
    <div class="panel-body">
        We have built partnerships with small farms around the world to
        hand-select beans at the peak of season. We then carefully roast
        in <a href="/batch-size">small batches</a> to maximize their
        potential.  </div>
</div>

下一段代碼是樣式的。你會在padding和border-radius使用em,標題的字號使用rem,以及border使用px。把下面代碼添加到你的樣式表吧。

 

.panel {                 
  padding: 1em;                    
  border-radius: 0.5em;            
  border: 1px solid #999;          
}
.panel > h2 {
  margin-top: 0;                   
  font-size: 0.8rem;               
  font-weight: bold;               
  text-transform: uppercase;       
}

這段代碼給面板添加了一個細邊框以及定義了標題的樣式。我希望標題的字號小一點,但要加粗和全是大寫。(你可以根據自己的設計,把字號改大點或者使用不同的排版方式)

第二個選擇器>是一個直接後代組合選擇符(direct descendant combinator),它代表的是.panel下的子元素h2。更完整的選擇器和組合選擇符的索引可以看附錄A。

在代碼片段2.13中,爲了更清晰看到效果,我給body添加了一個類panel-body,不過你會發現,在你自己的代碼裏是不需要的。因爲這個元素從根元素上繼承了字號大小,它已經是你想要看到的那樣。

讓這個面板變成‘響應式’

我們再更深入地看看這個問題。你可以根據屏幕尺寸的變化,添加媒體查詢來改變基礎字號大小,這可以令面板在不同尺寸的屏幕下,有不同的大小變化。

 

:root {                            1
  font-size: 0.75em;               1
}
@media (min-width: 800px) {        2
  :root {                          2
    font-size: 0.875em;            2
  }                                2
}                                  2
@media (min-width: 1200px) {       3
  :root {                          3
    font-size: 1em;                3
  }                                3
}
  • 1 針對所有屏幕,但是在更大的屏幕會被覆蓋
  • 2 針對比800px更寬的屏幕,覆蓋默認樣式代碼
  • 3 針對比1200px更寬的屏幕,覆蓋以上兩套樣式代碼

第一套樣式規則,聲明瞭小屏幕中的默認字號大小,這是我們想要在較小的屏幕上看到的字號大小。然後使用媒體查詢,把800px和1200px分別作爲兩個分水嶺逐級增加字號的大小,覆蓋掉默認的代碼。

針對頁面的根元素使用這些字號大小,響應式地重新定義em和rem對應的值,從而達到響應改變整個頁面的效果。儘管你沒有直接對這個面板做任何的修改,它現在是響應式的。在小屏幕上,譬如一臺手機,字號大小會被渲染成更小的(12px)。然後,在更大的屏幕上,寬大於800px和大於1200px的,組件的字號會分別放大到14px和16px。改變你的瀏覽器窗口,看看組件是怎麼變化的吧。

如果你在整個頁面中像這樣嚴格使用相對單位,整個頁面會隨着視窗大小放大和縮小。這會是你的響應式策略裏很重要的一部分。上面的2套媒體查詢聲明代碼,可以幫助你節省在頁面的其他部分使用媒體查詢的額外代碼。不過,如果你在元素中聲明的字號大小是以像素爲單位的,那就不會產生任何效果了。

類似地,如果你的老闆或者客戶覺得現在網站的字號太小或者太大,你隨時可以做到通過修改一行代碼影響到全局的元素,這項改變會影響到頁面上的其他元素,不費吹灰之力。

調整單個組件的大小

你也可以通過使用em縮放頁面上的一個獨立組件。有時,你可能會需要界面上的某些組件可以有個大號的版本。在我們的面板上這麼做吧,首先你需要給面板添加一個類名large:<div class="panel large">。

在下圖中,我們看到了面板的普通版和大號版的比較。效果類似響應式面板,但是兩種尺寸是可以同時在同一個頁面中使用的。

響應式

我們來對面板的字號聲明方式做一些小的修改。你還是在使用相對單位,但需要調整它們的基準值。第一點,給每個面板的父元素字號大小的定義font-size: 1rem。這裏指的是,不管在什麼地方使用這個面板,每個面板的字號大小是一個確定值。

第二點,使用em重新聲明標題的字號大小,而不使用rem,這樣標題就可以和剛纔聲明的父元素字號1rem關聯起來。下面是對應的代碼,更新下你的樣式表代碼吧。

[代碼片段創建一個面板的大號版本 ]

 

.panel {
  font-size: 1rem;               1
  padding: 1em;
  border: 1px solid #999;
  border-radius: 0.5em;
}
.panel > h2 {
  margin-top: 0;
  font-size: 0.8em;              2
  font-weight: bold;
  text-transform: uppercase;
}
  • 1 給組件聲明確定的字號大小
  • 2 其他元素的字號大小用em和父元素字號關聯

這些修改看起來並沒有影響面板的樣式,但是現在你已經準備好了,做一個大號的面板只需要修改一小行代碼。你需要做的,就是把父元素字號大小改寫成1rem以外的一個值。因爲其他元素的計算方式都依賴父元素的字號大小,只要修改它,整個面板的相關尺寸都會發生改變。添加下一個CSS代碼片段到你的樣式表,定義一個大號面板吧。

[ 代碼片段 利用一行代碼放大整個面板 ]

 

.panel.large {               1
  font-size: 1.2rem;
}
  • 1 組合選擇器指向同時有panel類和large類的元素

現在,你可以給普通面板添加class=”panel”和給大號面板添加class=”panel large”。類似地,你也可以定義一個小號版本,只需要把父元素的字號設得比1rem小。如果這個面板是一個更復雜的組件,包含多種字號大小或padding,也只需要一個聲明就可以重置大小,只要所有的子元素都是使用em聲明的。



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章