移動端適配方案,說多也不少。可使用百分比佈局,但百分比與em都是基於父元素進行計算的,在實際應用中不是很方便。使用rem不只能夠設置字體大小,塊大小也能夠設置。並且能夠良好的適配各類終端,因此這方案很受歡迎。javascript
rem定義及瀏覽器支持狀況css
rem(font size of the root element)是指相對於根元素的字體大小的單位。簡單的說它就是一個相對單位。看到rem必定會想起em單位,em(font size of the element)是指相對於父元素的字體大小的單位。它們之間其實很類似,只不過一個計算的規則是依賴根元素一個是依賴父元素計算。能夠先看看rem的瀏覽器支持狀況:html
能夠看到移動端基本支持:java
ios:6.1系統以上支持;android
android:2.1系統以上都支持;ios
桌面端IE支持狀況不樂觀。web
用法:瀏覽器
現代瀏覽器,IE9+,FireFox,Safari,Chrome,Opera,默認字體是16px,設置下根元素的字體大小爲16px:app
html { font-size:16px; }
,而後,若是但願某段文字的字體大小是12px,須要設置:iphone
p { font-size: 0.75rem; //12÷16=0.75(rem) }
塊大小的設置是相似的,因此整個佈局的關鍵就是設置根元素的字體大小了。設置好根元素字體大小值,佈局就能夠作到自適應了。
塊大小的設置,來個例子:
設置根元素字體大小爲37.5px,在iphone6裏面須要一個寬100px的塊,就是這樣了:
<!DOCTYPE html> <html> <meta charset="utf-8"></meta> <head> <title>vertical-align</title> <style type="text/css"> html{ font-size:37.5px; } #contentBox{ width:2.667rem; height:2.667rem; background:pink; } </style> </head> <body> <div id="contentBox"> </div> </body> </html>
若是在iphone5下想獲得一個100px的塊,須要設置基準值(即根元素字號)爲32px。
下面專門談談rem的基準值設置。
rem基準值設置
想要rem適配不一樣尺寸的設備,就須要針對不一樣設備設置合適的基準值,如上例所示。
問題來了,基準值設置成多少合適?
通常拿到的設計稿是375px(2倍稿)*2的,也就是iphone6的大小。那麼對於iphone6來講,基準值能夠設置爲37.5px。即設備寬度/10。這裏作了一個除以10的計算,是由於不但願font-size值太大。這樣使用rem時值也不會太大了。
若是是iphone5,基準值就是32px。
問題又來了,如何根據設備尺寸來設置基準值?
有兩個方法,經過css media query 和js添加基準值:
css media query:
@media (min-device-width : 375px) and (max-device-width : 667px) and (-webkit-min-device-pixel-ratio : 2){ html{font-size: 37.5px;} }
用media query來實現難覆蓋到全部設備:
html { font-size : 20px; } @media only screen and (min-width: 401px){ html { font-size: 25px !important; } } @media only screen and (min-width: 428px){ html { font-size: 26.75px !important; } } @media only screen and (min-width: 481px){ html { font-size: 30px !important; } } @media only screen and (min-width: 569px){ html { font-size: 35px !important; } } @media only screen and (min-width: 641px){ html { font-size: 40px !important; } }
而經過js來設置,能夠實現覆蓋全部設備:
js來設置:
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
關於方案的利弊,其實上面的例子裏面能夠看出,rem爲整數的時候,基準值爲32px,36px這樣的整數,換成px也是整數。但rem帶有小數,好比1.75rem,在32px的基準只下計算得56px。那再看看其餘機型的換算值:
表明機型 | 瀏覽器寬 | 對應尺寸 |
---|---|---|
iPhone 4/4s/5/5s | 320px | 56px |
Samsung Note 3, Nexus 5… | 360px | 63px |
iPhone 6 | 375px | 65.625px |
Google Nexus 6 | 412px | 72.1px |
iPhone 6 Plus | 414px | 72.45px |
能夠看出,有些機型裏面是有小數像素值的。小數像素可能會帶來必定的偏差,設計的同事像素眼很容易覺察到的。
在能夠接受的狀況下容許這些偏差存在。在安卓機子上較多出現這類狀況。
下面能夠具體看下小數像素在瀏覽器裏面的顯示狀況:
設置兩組塊,第一組是1.75rem*1.75rem的,第二組是1.85rem*1.85rem的,具體代碼以下:
.block{ display:inline-block; width:1.75rem; height:1.75rem; background:rgba(0,0,255, .5); } .block:nth-of-type(2n){ background:rgba(255,0,0, .5); } .group2 .block{ widrh:1.85rem; height:1.85rem; }
效果圖是
看下第一組塊,在iPhone6下,每一個塊的尺寸應該是:1.75*37.5=65.625px;
但實際狀況:
是的,瀏覽器會顯示爲65px或66px,並且沒有規律的來顯示。
這看起來有點難以想象,按道理來講,瀏覽器彷佛應該所有捨棄小數65px,或者保留到66px,可事實卻不是這樣的。
到這裏,能夠假設:瀏覽器所作的渲染處理只是做用在元素的渲染尺寸上,但他們的真實尺寸還是原始尺寸大小。
舉個實際的例子來講,就是一個元素的尺寸是0.625px,他的渲染尺寸是1px,剩下的0.375px由臨近元素填充;同理,若是一個元素是0.375px,其渲染尺寸是0px,可是會佔有臨近元素0.375px的空間。
而後帶着這個假設分析下上面的例子:
第一個塊的寬度爲 65.625px,根據四捨五入的原則其最終渲染尺寸爲 66px,空出的 0.375px 由第二個塊補上;
第二個塊向左補進 0.375px,至關於減小了 0.375px,餘下 65.25px,根據四捨五入的原則其最終渲染尺寸爲 65px,多出的 0.25px 會佔用第三個色的空間;
第三個塊被佔用了 0.25px,至關於增長了 0.25px,等於 65.875px,根據四捨五入的原則其最終渲染尺寸爲 66px,空出的 0.125px 由第四個塊補上;
第四個塊向左補進 0.125px,至關於減小了 0.125px,餘下 65.5px,根據四捨五入的原則其最終渲染尺寸爲 66px,空出的 0.5px 由第五個塊補上;
第五個塊向左補進 0.5px,至關於減小了 0.5px,餘下 65.125px,根據四捨五入的原則其最終渲染尺寸爲 65px,多出 0.125px;
這與瀏覽器的輸出結果是一致的,印證了猜測。
更具體的瀏覽器處理能夠看http://trac.webkit.org/wiki/LayoutUnit
其餘適配方案
也能夠採用固定佈局:
1.在viewport meta標籤上設置width=320,頁面的各個元素也採用px做爲單位。經過用JS動態修改標籤的initial-scale使得頁面等比縮放,從而恰好佔滿整個屏幕。
<meta name="viewport" content="width=320,user-scalable=no">
2.rem也可使用本身設置viewport和content的方法來適配,以方便計算和設置值:
例如:
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
其中dpr經過window.devicePixelRatio獲取,iphone6的值是2.
對於2倍稿,能夠直接設置基準值爲2倍,這樣就不用設計稿的值除以2了。
iphone6適配的設計稿750px,基準值設置爲75px就能夠了。
修改了縮放倍數以後,1px邊線的問題也同時解決了。
代碼:
<!DOCTYPE html> <html> <meta charset="utf-8"></meta> <meta name="viewport" content="" id="viewMeta"> <head> <title>vertical-align</title> <style type="text/css"> html{ font-size:75px; } #contentBox{ width:2.667rem; height:2.667rem; background:pink; border:1px solid #000; } </style> </head> <body> <div id="contentBox"> </div> </body> <script type="text/javascript"> var meta = document.getElementById('viewMeta'); var dpr = window.devicePixelRatio; meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no'); </script> </html>
圖圖:
參考: