本文結合本身對網易與淘寶移動端首頁html元素上的font-size這個屬性的思考與學習,討論html5設計稿尺寸以及前端與設計之間協做流程的問題,內容較多,但對你的技術和工做必定有價值,歡迎閱讀和點評:)。html
最近閱讀白樹的博文《移動web資源整理》時,他在博文中有一段指出,若是html5要適應各類分辨率的移動設備,應該使用rem這樣的尺寸單位,同時給出了一段針對各個分辨率範圍在html上設置font-size的代碼:前端
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,該類在不一樣分辨率下對應的實際寬度以下:html5
321px <= device-width <= 375px,font-size:11px ---> .item的width:34px 376px <= device-width <= 414px,font-size:12px ---> .item的width:37.4px 415px <= device-width <= 639px,font-size:15px ---> .item的width:40.8px 640px <= device-width <= 719px,font-size:20px ---> .item的width:51px 720px <= device-width <= 749px,font-size:22.5px ---> .item的width:76.5px 750px <= device-width <= 799px,font-size:23.5px ---> .item的width:79.8999999px 800px <= device-width ,font-size:25px ---> .item的width:85px
以上代碼乍看沒啥問題,響應式設計不就應該是這麼幹的嗎?可是從工做量和複雜度方面來考慮,它有如下幾個不足:git
正是由於以上提到的一些不足,我以爲這種適配方式不是特別好,寫起來太麻煩。爲了完成工做,咱們須要找尋更簡單更有效率的方法。那麼html5該如何去作衆多移動設備的適配呢?我目前已知的有3種解決方法,將會在下文的第2,3,4部分闡述,若是你閱讀以後,有什麼想法,儘可在評論中與我交流。github
我以爲有些web app並必定很複雜,好比拉勾網,你看看它的頁面在iphone4,iphone6,ipad下的樣子就知道了:web
它的頁面有一個特色,就是:sass
這種app是一種典型的彈性佈局:關鍵元素高寬和位置都不變,只有容器元素在作伸縮變換。對於這類app,記住一個開發原則就好:文字流式,控件彈性,圖片等比縮放。以圖描述:app
這個規則是一套基本的適配規則,對於這種簡單app來講已經足夠,同時它也是後面要說的rem佈局的基礎。另外對於拉勾這種app可能須要額外媒介查詢對佈局進行調整的就是小屏幕設備。舉例來講,由於如今不少設計稿是根據iphone6的尺寸來的,而iphon6設備寬的邏輯的像素是375px,而iphone4的邏輯像素是320個像素,因此若是你根據設計稿作出來的東西,在iphone4裏面可能顯示不下,好比說拉鉤網底部那個下載框,你對比看下就知道了,這是4:less
這是6:
6下面兩邊的間距比4多不少,說明拉勾對4確定是作過適配的,從代碼也能夠證明這一點:
不過若是你拿到的是根據4的設計稿,那就沒有問題,比4分辨率大的設備確定能顯示根據4的尺寸作出來的東西。
還有一點,這種狀況css尺寸單位用px就好,不要用rem,避免增長複雜度。
先來看看網易在不一樣分辨率下,呈現的效果:
從上面幾張圖能夠看出,隨着分辨率的增大,頁面的效果會發生明顯變化,主要體如今各個元素的寬高與間距。375*680的比320*680的導航欄明顯要高。可以達到這種效果的根本緣由就是由於網易頁面裏除了font-size以外的其它css尺寸都使用了rem做爲單位,好比你看導航欄的高度設置代碼:
但是在本文第1部分提到,使用rem佈局結合在html上根據不一樣分辨率設置不一樣font-size有不少很差解決的麻煩,網易是如何解決的呢?最根本的緣由在於,網易頁面上html的font-size不是預先經過媒介查詢在css裏定義好的,而是經過js計算出來的,因此當分辨率發生變化時,html的font-size就會變,不過這得在你調整分辨率後,刷新頁面才能看獲得效果。你看代碼就知道爲啥font-size是直接寫到html的style上面的了(js設置的緣由):
它是根據什麼計算的,這就跟設計稿有關了,拿網易來講,它的設計稿應該是基於iphone4或者iphone5來的,因此它的設計稿豎直放時的橫向分辨率爲640px,爲了計算方便,取一個100px的font-size爲參照,那麼body元素的寬度就能夠設置爲width: 6.4rem,因而html的font-size=deviceWidth / 6.4。這個deviceWidth就是viewport設置中的那個deviceWidth。根據這個計算規則,可得出本部分開始的四張截圖中html的font-size大小以下:
deviceWidth = 320,font-size = 320 / 6.4 = 50px deviceWidth = 375,font-size = 375 / 6.4 = 58.59375px deviceWidth = 414,font-size = 414 / 6.4 = 64.6875px deviceWidth = 500,font-size = 500 / 6.4 = 78.125px
事實上網易就是這麼幹的,你看它的代碼就知道,body元素的寬是:
根據這個能夠確定它的設計稿豎着時的橫向分辨率爲640。而後你再看看網易在分辨率爲320*680,375*680,414*680,500*680時,html的font-size是否是與上面計算的一致:
這個deviceWidth經過document.documentElement.clientWidth就能取到了,因此當頁面的dom ready後,作的第一件事情就是:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';
這個6.4怎麼來的,固然是根據設計稿的橫向分辨率/100得來的。下面總結下網易的這種作法:
若是設計稿基於iphone6,橫向分辨率爲750,body的width爲750 / 100 = 7.5rem 若是設計稿基於iphone4/5,橫向分辨率爲640,body的width爲640 / 100 = 6.4rem
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';
@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} }
最後還有2個狀況要說明:
第一,若是採用網易這種作法,視口要以下設置:
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
第二,當deviceWidth大於設計稿的橫向分辨率時,html的font-size始終等於橫向分辨率/body元素寬:
之因此這麼幹,是由於當deviceWidth大於640時,則物理分辨率大於1280(這就看設備的devicePixelRatio這個值了),應該去訪問pc網站了。事實就是這樣,你從手機訪問網易,看到的是觸屏版的頁面,若是從pad訪問,看到的就是電腦版的頁面。若是你也想這麼幹,只要把總結中第三步的代碼稍微改一下就好了:
var deviceWidth = document.documentElement.clientWidth; if(deviceWidth > 640) deviceWidth = 640; document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';
看看淘寶在不一樣分辨率下,呈現的效果:
淘寶的效果跟網易的效果實際上是相似的,隨着分辨率的變化,頁面元素的尺寸和間距都相應變化,這是由於淘寶的尺寸也是使用了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的方法以下:
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
淘寶佈局的第二個要點,就是html元素的font-size的計算公式,font-size = deviceWidth / 10:
接下來要解決的問題是,元素的尺寸該如何計算,好比說設計稿上某一個元素的寬爲150px,換算成rem應該怎麼算呢?這個值等於設計稿標註尺寸/該設計稿對應的html的font-size。拿淘寶來講的,他們用的設計稿是750的,因此html的font-size就是75,若是某個元素時150px的寬,換算成rem就是150 / 75 = 2rem。總結下淘寶的這些作法:
var scale = 1 / devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
最後還有一個狀況要說明,跟網易同樣,淘寶也設置了一個臨界點,當設備豎着時橫向物理分辨率大於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; }
前端與設計師的協做應該是比較簡單的,最重要的是要規範設計提供給你的產物,一般對於前端來講,咱們須要設計師提供標註尺寸後的設計稿以及各類元素的切圖文件,有了這些就能夠開始佈局了。考慮到Retina顯示屏以及這麼多移動設備分辨率卻不同的問題,那麼設計師應該提供多套設計稿嗎?從網易和淘寶的作法來看,應該是不用了,咱們能夠按照設計稿,先作出一套佈局,按照以上方法作適配,因爲是等比適配,因此各個設備的視覺效果差別應該會很小,固然也排除不了一些須要媒介查詢特殊處理的狀況,這確定避免不了的。下面這張圖是淘寶設計師分享的他們的工做流程:
解釋一下就是:
第一步,視覺設計階段,設計師按寬度750px(iPhone 6)作設計稿,除圖片外全部設計元素用矢量路徑來作。設計定稿後在750px的設計稿上作標註,輸出標註圖。同時等比放大1.5倍生成寬度1125px的設計稿,在1125px的稿子裏切圖。
第二步,輸出兩個交付物給開發工程師:一個是程序用到的@3x切圖資源,另外一個是寬度750px的設計標註圖。
第三步,開發工程師拿到750px標註圖和@3x切圖資源,完成iPhone 6(375pt)的界面開發。此階段不能用固定寬度的方式開發界面,得用自動佈局(auto layout),方便後續適配到其它尺寸。
第四步,適配調試階段,基於iPhone 6的界面效果,分別向上向下調試iPhone 6 plus(414pt)和iPhone 5S及如下(320pt)的界面效果。由此完成大中小三屏適配。
注意第三步,就要使用咱們以上介紹的網易跟淘寶的適配方法了。假如公司設計稿不是基於750的怎麼辦,其實很簡單,按上圖作一些相應替換便可,可是流程和方法仍是同樣的。解釋一下爲何要在@3x的圖裏切,這是由於如今市面上也有很多像魅藍note這種超高清屏幕,devicePixelRatio已經達到3了,這個切圖保證在全部設備都清晰顯示。
總算是羅裏吧嗦地把文章寫完了, 但願你還以爲滿意,這篇文章對我來講價值也很大,從此作html5的項目就有思路了,本文提到的三種方法未來確定都有用武之地。最後,歡迎你們在評論裏與我交流你對本文的見解,咱們能夠一塊兒交流,一塊兒進步。