最近翻了一下關於移動端的rem的使用,怎樣最方便。在讀到流雲諸葛的一篇關於《從網易與淘寶的font-size思考前端設計稿與工做流》的文章後,來總結一下。javascript
然而根據我以往作移動端web項目的時候,設計稿通常是640或者750的,我通常會在head裏面這樣寫:css
<meta name="viewport" content="width=750, user-scalable=no, target-densitydpi=device-dpi"><!-- width取值與頁面定義的寬度一致 -->
作移動端活動的時候結構也通常這樣:html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="yes" name="apple-mobile-web-app-capable"> <!-- ios7.0版本之後,safari上已看不到效果,能夠刪除--> <meta content="black" name="apple-mobile-web-app-status-bar-style"> <meta content="telephone=no" name="format-detection"> <meta content="email=no" name="format-detection"> <title>viewport通用</title> <script type="text/javascript"> var phoneWidth = parseInt(window.screen.width); var phoneScale = phoneWidth / 750; var ua = navigator.userAgent; if (/Android (\d+\.\d+)/.test(ua)) { var version = parseFloat(RegExp.$1); if (version > 2.3) { document.write('<meta name="viewport" id="vie" content="width=750, minimum-scale = ' + phoneScale + ', maximum-scale = ' + phoneScale + ', target-densitydpi=device-dpi">'); } else { document.write('<meta name="viewport" id="vie" content="width=750, target-densitydpi=device-dpi">'); } } else { document.write('<meta id="vie" name="viewport" content="width=750, user-scalable=no, target-densitydpi=device-dpi, minimal-ui">'); } </script> <link style="text/css" rel="stylesheet" href="home.css"> <script type="text/javascript" src="js/app.js"></script> </head> <body> <!--頁面內容--> </body> </html>
通常的移動頁面通用寫法:前端
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
也就是下面要想總結的。html5
在博客園白樹的博文中有一段指出,若是html5要適應各類分辨率的移動設備,應該使用rem這樣的尺寸單位,同時給出了一段針對各個分辨率範圍在html上設置font-size的代碼:java
html{font-size:10px} @media screen and (min-width:321px) and (max-width:375px){html{font-size:11px}} @media screen and (min-width:376px) and (max-width:414px){html{font-size:12px}} @media screen and (min-width:415px) and (max-width:639px){html{font-size:15px}} @media screen and (min-width:640px) and (max-width:719px){html{font-size:20px}} @media screen and (min-width:720px) and (max-width:749px){html{font-size:22.5px}} @media screen and (min-width:750px) and (max-width:799px){html{font-size:23.5px}} @media screen and (min-width:800px){html{font-size:25px}}
在實際項目中,把與元素尺寸有關的css,如width,height,line-height,margin,padding等都以rem做爲單位,這樣頁面在不一樣設備下就能保持一致的網頁佈局。舉例來講,網頁有一個.item類,設置了width爲3.4rem,該類在不一樣分辨率下對應的實際寬度以下:ios
321px <= device-width <= 375px,font-size:11px ---> .item的width:(11*3.4)px
376px <= device-width <= 414px,font-size:12px ---> .item的width:(12*3.4)px
415px <= device-width <= 639px,font-size:15px ---> .item的width:(15*3.4)px
640px <= device-width <= 719px,font-size:20px ---> .item的width:(20*3.4)px
720px <= device-width <= 749px,font-size:22.5px ---> .item的width:(22.5*3.4)px
750px <= device-width <= 799px,font-size:23.5px ---> .item的width:(23.5*3.4)px
800px <= device-width ,font-size:25px ---> .item的width:(25*3.4)px
注:說明一下,在流雲諸葛的那篇文章中,上面的font-size爲11px的時候,item類的width爲34px,爲啥不是(11*3.4)px。難道這兒的font-size不是設置的html的font-size?git
上面一看,缺點實際上是不少的,我以爲要這樣作估計頁面不多,或者是一個啥活動頁面這樣寫兼容也能夠。主要缺陷有兩點以下:github
有些web app的設計搞確實不復雜,比較簡單,好比拉勾網的佈局結構如圖所示:web
它的頁面有一個特色,就是:
這種app是一種典型的彈性佈局:關鍵元素高寬和位置都不變,只有容器元素在作伸縮變換。對於這類app,記住一個開發原則就好:文字流式,控件彈性,圖片等比縮放。
總之一句話,簡單的設計稿,簡單處理,沒必要寫得那麼複雜。
第一,視口設置以下:
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
第二,當deviceWidth大於設計稿的橫向分辨率時,html的font-size始終等於橫向分辨率/body元素寬:
如圖所示:
640*680
641*680
之因此這麼幹,是由於當deviceWidth大於640時,則物理分辨率大於1280(這就看設備的devicePixelRatio這個值了),應該去訪問pc網站了。事實就是這樣,你從手機訪問網易,看到的是觸屏版的頁面,若是從pad訪問,看到的就是電腦版的頁面。
在dom ready之後,經過如下代碼設置html的font-size:
var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 640) deviceWidth = 640; document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';
這個6.4怎麼來的,固然是根據設計稿的橫向分辨率/100得來的。
若是設計稿基於iphone6,橫向分辨率爲750,body的width爲750 / 100 = 7.5rem
若是設計稿基於iphone4/5,橫向分辨率爲640,body的width爲640 / 100 = 6.4rem
6.4只是舉個例子,若是是750的設計稿,應該除以7.5。
font-size可能須要額外的媒介查詢,而且font-size不能使用rem,如網易的設置:
@media screen and (max-width:321px){ .m-navlist{font-size:15px} } @media screen and (min-width:321px) and (max-width:400px){ .m-navlist{font-size:16px} } @media screen and (min-width:400px){ .m-navlist{font-size:18px} }
研究了下網易新聞手機端的頁面,沒有對字體使用px單位,仍是用的是rem。
淘寶的效果跟網易的效果實際上是相似的,隨着分辨率的變化,頁面元素的尺寸和間距都相應變化,這是由於淘寶的尺寸也是使用了rem的緣由。在介紹它的作法以前,先來了解一點關於viewport的知識,一般咱們採用以下代碼設置viewport:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
這樣整個網頁在設備內顯示時的頁面寬度就會等於設備邏輯像素大小,也就是device-width。這個device-width的計算公式爲:
設備的物理分辨率/(devicePixelRatio * scale),在scale爲1的狀況下,device-width = 設備的物理分辨率/devicePixelRatio 。
devicePixelRatio稱爲設備像素比,每款設備的devicePixelRatio都是已知,而且不變的,目前高清屏,廣泛都是2,不過還有更高的,好比2.5, 3 等,魅族note的手機的devicePixelRatio就是3。淘寶觸屏版佈局的前提就是viewport的scale根據devicePixelRatio動態設置:
在devicePixelRatio爲2的時候,scale爲0.5
在devicePixelRatio爲3的時候,scale爲0.3333
這麼作目的固然是爲了保證頁面的大小與設計稿保持一致了,好比設計稿若是是750的橫向分辨率,那麼實際頁面的device-width,以iphone6來講,也等於750,這樣的話設計稿上標註的尺寸只要除以某一個值就可以轉換爲rem了。經過js設置viewport的方法以下:
淘寶佈局的第二個要點,就是html元素的font-size的計算公式,font-size = deviceWidth / 10:
接下來要解決的問題是,元素的尺寸該如何計算,好比說設計稿上某一個元素的寬爲150px,換算成rem應該怎麼算呢?這個值等於設計稿標註尺寸/該設計稿對應的html的font-size。拿淘寶來講的,他們用的設計稿是750的,因此html的font-size就是75,若是某個元素時150px的寬,換算成rem就是150 / 75 = 2rem。總結下淘寶的這些作法:
(1)動態設置viewport的scale
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
(2)動態計算html的font-size
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
(3)佈局的時候,各元素的css尺寸=設計稿標註尺寸/設計稿橫向分辨率/10
(4)font-size可能須要額外的媒介查詢,而且font-size不使用rem,這一點跟網易是同樣的。
最後還有一個狀況要說明,跟網易同樣,淘寶也設置了一個臨界點,當設備豎着時橫向物理分辨率大於1080時,html的font-size就不會變化了,緣由也是同樣的,分辨率已經能夠去訪問電腦版頁面了。
關於這種作法的具體實現,淘寶已經給咱們提供了一個開源的解決方案,具體請查看:
https://github.com/amfe/lib-flexible
共同點:
不一樣點:
//定義一個變量和一個mixin @baseFontSize: 75;//基於視覺稿橫屏尺寸/100得出的基準font-size .px2rem(@name, @px){ @{name}: @px / @baseFontSize * 1rem; } //使用示例: .container { .px2rem(height, 240); } //less翻譯結果: .container { height: 3.2rem; }