前段時間試譯了Keith J.Grant的CSS好書《CSS in Depth》,其中的第二章《Working with relative units》,書中對relative units的講解和舉例能夠說至關全面,看完以後發現本身並不太懂CSS相對單位,也但願分享給你們,因此有了這個譯文系列。(如有勘誤或翻譯建議,歡迎 Github PR ^_^
)css
《別說你懂CSS相對單位》系列譯文:html
本文對應的章節目錄:前端
2.2 em和remgit
2.2.2 對font-size使用remgithub
2.3 中止使用像素思惟去思考瀏覽器
當瀏覽器解析HTML文檔時,建立了一個用來表明頁面元素的集合,叫作DOM(文檔對象模型,Document Object Model)。樹狀結構,每個節點表明一個元素。<html>
就是頂層節點(根節點),在下面的是它的子節點<head>
和<body>
,再往下就是它們的子節點,還有後代節點,如此類推。less
根節點是文檔裏全部其餘元素的祖先。它有一個特別的僞類(pseudo-class)選擇器(:root),在樣式表裏能夠用這個選擇器表示。使用帶類名的類型選擇器html,或者直接用標籤選擇器,效果是同樣的。工具
rem是根em(root em)的縮寫。rem是和根元素關聯的,不依賴當前元素。無論你在文檔中的什麼地方使用這個單位,1.2rem的計算值是相等的,等於1.2倍的根元素的字號大小。下面的示例代碼中,聲明瞭根元素的字號大小,並在嵌套的無序列表中使用rem聲明字號大小。post
[ 代碼片斷 2.10 使用rem聲明字號大小 ]優化
:root { 1 font-size: 1em; 2 } ul { font-size: .8rem; }
在這個示例裏,根字號大小是瀏覽器的默認大小16px(根元素的1em等於瀏覽器的默認字號大小)。無序列表的字號大小爲0.8rem,計算結果是12.8px。由於這隻跟根元素相關,儘管你在列表裏嵌套了列表,嵌套子列表的字號仍然保持不變。
可用性:對font-size使用相對長度單位
一些瀏覽器會提供給用戶2種方式定製文字的大小:縮放和設置一個默認的字號大小。經過按Ctrl+或者Ctrl-,用戶能夠對頁面進行縮放。這在視覺上會把整個頁面的文字或圖片(實際上是全部元素)都放大或縮小了。在一些瀏覽器,這個改變只針對當前的標籤頁且是臨時的,不會影響到新開的標籤頁。
設置默認字號大小,會有點不同。不只僅是設置的入口比較難找(通常在瀏覽器的設置頁),並且這個設置是永久的,直到用戶把默認值還原。值得注意的是,這個設置對使用px或其餘絕對單位定義的字號大小無效。由於默認字號大小對一些用戶是必要的,尤爲是弱視的羣體,你應該用相對單位或百分比來定義字號的大小。
rem簡化了不少em帶來的複雜度。事實上,rem提供了一個在px和em間的相對單位折中解決方案,並且更易於使用。那麼,是否是意味着你應該在對全部元素都使用rem,去掉其餘長度單位呢?固然不是。
在CSS的世界裏,這個答案一般是,看狀況。rem只是你的工具箱中的其中一個。掌握CSS很重要的一點,就是學會分辨在什麼場景下該使用什麼工具。個人選擇是,對font-size
使用rem,對border使用px,對其餘的度量方式如padding
、margin
、border-radius
等使用em。然而在必要時,須要聲明容器的寬度的話,我更喜歡使用百分比。
這樣,字號大小就變得可預測,而當其餘因素影響到元素的字號大小時,你也能夠藉助em去縮放元素的padding和margin。在border上使用像素是很合適的,尤爲當你想要一根漂亮的線的時候。以上就是我對不一樣屬性使用不一樣單位的理想方案,不過我要再次聲明,這些都是工具,在某些特定場景下,利用不一樣的工具可能取到更好的效果。
提示當你不肯定的時候,對
font-size
使用rem,對border
使用px,以及對其餘大多數屬性使用em。
把頁面的根元素字號大小定義爲0.625em或者62.5%,在最近幾年來,這樣的用法很常見,這是一種模式,或者更貼切地說,這是一種反模式。
[ 代碼片斷 2.11 反模式:全局地把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的時候咱們也須要這樣作。(在第13章,咱們會有更具體的方式來優化這個實現方式。)
當使用em時,咱們很容易陷入糾結,這個值轉化成像素值會是多少呢?尤爲對於字號大小。你一直在乘和除以em值,這樣你很快就會瘋掉了。相反,我但願你能夠接受一項挑戰,嘗試培養先開始使用em的習慣。若是你習慣使用像素,那轉成em是須要必定時間和練習的,但相信我,這很值得。
這不是在說你不再使用像素了。若是你跟一個設計師合做,你可能須要用更精確的像素值去溝通,這沒問題的。在項目的開始,你須要聲明一個基礎的字號大小(一般是對標題或者標註的經常使用字號)。使用絕對值去描述大小,每每會更加容易。
轉換成rem會有計算環節,那就讓計算器去忙吧(一般我會在Mac電腦上按cmd+空格
,在Spotlight裏計算)。首先在根元素上聲明根字號大小,從那開始,使用像素應該是例外的狀況,而不是常態。
在這章內容裏,我仍是會持續地聊起像素。這會有助於我解釋相對單位的工做原理,同時也能幫助你培養計算em值的習慣。在這章以後,我基本會使用相對單位來討論字號的大小。
先假設你想把默認字號設定爲14px。把10px設定爲基準值,再在頁面中去覆蓋它的寫法,咱們不推薦這種寫法,相反,你應該在根元素上直接聲明一個值。
在這個代碼片斷裏,目標字號值是繼承的,瀏覽器的默認值16px,那麼14/16 = 0.875。
把下面的代碼添加到一個新的樣式表的最上面,咱們會在這上面添加其餘代碼。這裏設定根元素(<html>
)的默認字號大小。
[ 代碼片斷 2.12 設定正確的默認字號大小 ]
:root { 1 font-size: 0.875em; 2 }
如今,你的指望基準字號14px對整個頁面的元素有效,你不須要在其餘地方從新聲明瞭。你只須要在設計不同的地方修改爲新的字號,譬如標題。
咱們一塊兒來建立圖2.7那樣的面板吧!你建立的這個面板,基於14px字號,使用相對單位。
[ 圖 2.7 使用相對單位和繼承字號的面板 ]
下面是模板,加到你的頁面吧。
[ 代碼片斷 2.13 面板的模板 ]
<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
。把下面代碼添加到你的樣式表吧。
[ 代碼片斷 2.14 使用相對單位的面板 ]
.panel { padding: 1em; 1 border-radius: 0.5em; 1 border: 1px solid #999; 2 } .panel > h2 { margin-top: 0; 3 font-size: 0.8rem; 4 font-weight: bold; 4 text-transform: uppercase; 4 }
這段代碼給面板添加了一個細邊框以及定義了標題的樣式。我但願標題的字號小一點,但要加粗和全是大寫。(你能夠根據本身的設計,把字號改大點或者使用不一樣的排版方式)
第二個選擇器>
是一個直接後代組合選擇符(direct descendant combinator),它表明的是.panel
下的子元素h2
。更完整的選擇器和組合選擇符的索引能夠看附錄A。
在代碼片斷2.13中,爲了更清晰看到效果,我給body
添加了一個類panel-body
,不過你會發現,在你本身的代碼裏是不須要的。由於這個元素從根元素上繼承了字號大小,它已是你想要看到的那樣。
咱們再更深刻地看看這個問題。你能夠根據屏幕尺寸的變化,添加媒體查詢來改變基礎字號大小,這能夠令面板在不一樣尺寸的屏幕下,有不一樣的大小變化。(見圖2.8)
[ 圖 2.8 在不一樣屏幕大小的響應式面板:300px(左上角),800px(右上角),1440px(下面) ]
媒體查詢(media query) —— 經過
@media
規則來聲明樣式,在不一樣的屏幕尺寸或者媒體類型(如打印機或顯示器)下,觸發對應的樣式控制。這是響應式設計的關鍵要素。詳情看代碼片斷2.15的這個例子,我在第8章會更深刻的討論媒體查詢這個話題。
爲了實現上面說的效果,把你的樣式代碼改爲這樣。
[ 代碼片斷 2.15 ]
:root { 1 font-size: 0.75em; 1 } 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 }
第一套樣式規則,聲明瞭小屏幕中的默認字號大小,這是咱們想要在較小的屏幕上看到的字號大小。而後使用媒體查詢,把800px和1200px分別做爲兩個分水嶺逐級增長字號的大小,覆蓋掉默認的代碼。
針對頁面的根元素使用這些字號大小,響應式地從新定義em和rem對應的值,從而達到響應改變整個頁面的效果。儘管你沒有直接對這個面板作任何的修改,它如今是響應式的。在小屏幕上,譬如一臺手機,字號大小會被渲染成更小的(12px)。而後,在更大的屏幕上,寬大於800px和大於1200px的,組件的字號會分別放大到14px和16px。改變你的瀏覽器窗口,看看組件是怎麼變化的吧。
若是你在整個頁面中像這樣嚴格使用相對單位,整個頁面會隨着視窗大小放大和縮小。這會是你的響應式策略裏很重要的一部分。上面的2套媒體查詢聲明代碼,能夠幫助你節省在頁面的其餘部分使用媒體查詢的額外代碼。不過,若是你在元素中聲明的字號大小是以像素爲單位的,那就不會產生任何效果了。
相似地,若是你的老闆或者客戶以爲如今網站的字號過小或者太大,你隨時能夠作到經過修改一行代碼影響到全局的元素,這項改變會影響到頁面上的其餘元素,不費吹灰之力。
你也能夠經過使用em縮放頁面上的一個獨立組件。有時,你可能會須要界面上的某些組件能夠有個大號的版本。在咱們的面板上這麼作吧,首先你須要給面板添加一個類名large
:<div class="panel large">
。
在圖2.9,咱們看到了面板的普通版和大號版的比較。效果相似響應式面板,可是兩種尺寸是能夠同時在同一個頁面中使用的。
[ 圖 2.9 在一個頁面上的普通尺寸面板和大號面板 ]
咱們來對面板的字號聲明方式作一些小的修改。你仍是在使用相對單位,但須要調整它們的基準值。第一點,給每一個面板的父元素字號大小的定義font-size: 1rem
。這裏指的是,無論在什麼地方使用這個面板,每一個面板的字號大小是一個肯定值。
第二點,使用em從新聲明標題的字號大小,而不使用rem,這樣標題就能夠和剛纔聲明的父元素字號1rem關聯起來。下面是對應的代碼,更新下你的樣式表代碼吧。
[ 代碼片斷 2.16 建立一個面板的大號版本 ]
.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; }
這些修改看起來並無影響面板的樣式,可是如今你已經準備好了,作一個大號的面板只須要修改一小行代碼。你須要作的,就是把父元素字號大小改寫成1rem之外的一個值。由於其餘元素的計算方式都依賴父元素的字號大小,只要修改它,整個面板的相關尺寸都會發生改變。添加下一個CSS代碼片斷到你的樣式表,定義一個大號面板吧。
[ 代碼片斷 2.17 利用一行代碼放大整個面板 ]
.panel.large { 1 font-size: 1.2rem; }
如今,你能夠給普通面板添加class="panel"
和給大號面板添加class="panel large"
。相似地,你也能夠定義一個小號版本,只須要把父元素的字號設得比1rem小。若是這個面板是一個更復雜的組件,包含多種字號大小或padding,也只須要一個聲明就能夠重置大小,只要全部的子元素都是使用em聲明的。
《別說你懂CSS相對單位》系列譯文:
章節:
2.1 相對單位值的魔力
2.2 em和rem
2.2.1 對font-size使用em
2.2.2 對font-size使用rem
2.3 中止使用像素思惟去思考
2.4 視口相關單位(viewport-relative units)
2.6 自定義屬性(也叫「CSS變量」)
原著版權信息:做者:Keith J.Grant
書籍:CSS in Depth
章節:Working with relative units
筆者 @Yuying Wu,前端愛好者 / 鼓勵師 / 新西蘭打工度假 / 鏟屎官。目前就任於某大型電商的B2B前端團隊。
感謝你讀到這裏,對上文如有任何疑問或建議,歡迎留言。
若是你和我同樣喜歡前端,喜歡搗騰獨立博客或者前沿技術,或者有什麼職業疑問,歡迎關注我以及各類交流哈。
獨立博客:wuyuying.com
知乎ID:@Yuying Wu
Github:Yuying Wu