最近看到這樣一個提問:我有一個750 x 1500尺寸的設計稿,設計稿上有一個150 x 50的按鈕,那麼在寫頁面佈局的時候,應該如何肯定按鈕的尺寸呢?。大多數同窗在回答的時候提到了rem。但我發現不少同窗對於rem的實際應用還存在一點小小的疑問和誤解。css
因而問題來了,rem究竟是什麼?rem是爲了解決什麼問題而存在的?rem可以給咱們帶來什麼樣的便利?帶着這樣的問題,咱們一塊兒來總結一下rem的實踐。恰好工做中有一個移動端頁面的需求要作,就嘗試使用rem完成了一個小小的頁面適配。你們能夠點擊這裏,查看rem適配demo,html
建議你們在chrome的device module下打開,經過切換不一樣手機的模擬器來查看不一樣尺寸下的區別。ios
rem是一個相對於根元素字體大小的css單位。與px同樣,他能夠用來設置字體大小,也能夠用來設置長度單位。相對於根元素字體大小是什麼意思?web
舉個栗子。在頁面中,html元素是根元素,所以咱們首先給html設置一個字體大小chrome
html { font-size: 100px; }
因而,在整個頁面中,就有這樣的換算公式 : 1rem = 100px
segmentfault
因此若是一個按鈕,有以下的css樣式,就等同於他的寬爲100px,高50px.瀏覽器
btn { width: 1rem; height: 0.5rem; }
這就是rem這個知識點的全部真相了。app
!!!什麼?這就完了?這和px有什麼區別?iphone
對啊,這和px原本就沒有特別的區別,就是一個尺寸單位嘛!佈局
因此提問的那個同窗拿着750x1500設計圖來問,當咱們設置爲html的字體大小爲100px時,
150x50的按鈕應該在頁面裏面寫什麼尺寸?,用px就應該寫 75x25,用rem就是 0.75 x 0.25.
真實寬度375px / 設計圖寬度750px = 按鈕真實寬度 / 設計圖按鈕寬度150px ==> 按鈕真實寬度 = 75px 又 1rem = 100px; ==> 75px = 0.75rem
有的時候咱們但願在設計圖直接量出來的尺寸不用除2直接獲得rem的值,也就是說量出來是150px,那麼用rem表示就是1.5rem。這個時候咱們只須要修改html的字體大小爲50px便可。那麼計算思路就有一點不一樣。
真實寬度375px / 設計圖寬度750px = 按鈕真實寬度 / 設計圖按鈕寬度150px ==> 按鈕真實寬度 = 75px 又 1rem = 50px; ==> 75px = 1.5rem
所以當設計圖的尺寸發生改變時,咱們須要根據上述思路,動態的調整html的字體大小,以達到咱們想要的rem換算。
以iphone各類手機的尺寸來講,iPhone4,5 寬度320px,iPhone6 375px,iPhone6 plus 414px. 若是一個按鈕,固定一個75x25的尺寸,那麼就必然會致使在不一樣尺寸下的相對大小不同。這帶來的問題就在於會直接影響到設計的美觀,可能在iPhone6下,一個完美的設計圖,到了iPhone5,就變得low不少。 由於,爲了讓頁面元素的尺寸可以在設備寬度變化的時候也跟着變化,rem就出現了。
咱們已經知道,rem的相對大小跟html元素的字體大小有關係。使用rem適配的原理就是咱們只須要在設備寬度大小變化的時候,調整html的字體大小,那麼頁面上全部使用rem單位的元素都會相應的變化。 這也是rem與px最大的區別。
有css與js兩種方式來調整html元素大小的值。
css方式
html { font-size: calc(100vw / 3.75) }
100vw表示設備寬度,除以3.75這裏是以iphone6 的寬度375px爲標準,爲了保證html的字體大小爲100px。這樣咱們在換算的時候,1px 就是0.01rem,就很容易計算。
由於chrome下最小字體大小爲12px,因此不能把html的font-size設置成1px或者10px,100px是咱們最好的選擇。
js方式, 原理與css同樣,不過爲了不在一些老舊一點的手機瀏覽器上不支持calc,vm這些屬性,在實際應用中使用js是最好的。
!function () { function a() { var _width; var clientWidth = document.documentElement.clientWidth; if (clientWidth > 568) { _width = 568; } else if (clientWidth < 320) { _width = 320; } else { _width = clientWidth; } // var pageWid = (window.innerWidth > document.querySelector('body').offsetHeight) ? 1136 : 640; document.documentElement.style.fontSize = _width / 375 * 100 + "px"; } var b = null; document.addEventListener("DOMContentLoaded", function () { window.addEventListener("resize", function () { clearTimeout(b); b = setTimeout(a, 300) }, !1); a() }, false); }(window);
在實踐中還有一個關鍵的問題須要處理。就是不管如何js的加載會比css慢,所以若是咱們就這樣的話,頁面的元素會有一個很明顯的閃爍過程,由於再js加載進來以前,html的字體大小尚未達到咱們想要的效果。所以一般咱們須要在css中,給html的字體大小設置一個默認值,以弱化這個閃爍的過程。默認值的具體大小須要咱們自行根據設計圖的尺寸,以及你想要的結果,經過上面咱們介紹的計算思路去得出。
html { font-size: 100px; }
1、rem的適用性頗有侷限,僅僅只可以用於只在移動端展現的頁面。若是你的頁面還須要適配到pc端,那麼就老老實實的使用px吧。在上面的實現中,我經過判斷設定了html字體大小的範圍來避免pc上顯示過於誇張。
2、有的同窗可能對web的適配有點誤解。web中作適配並不須要考慮什麼物理像素啊,dpi等等概念。這些應該僅僅只是Android或者ios原生app纔會考慮的問題。這些誤會致使許多搞設計的同窗在給web app作設計的時候,也丟一張1080 x 1920 的設計稿過來,真是愁死人了。