以前寫了一篇文章《一篇真正教會你開發移動端一面的文章(一)》。那是本篇文章的基礎,若是沒有閱讀過的同窗能夠去看看,今天就給你們帶來乾貨,真真正正的講到如何很好的開發一個移動端的頁面javascript
好了,讓咱們開始吧,從哪裏開始呢?從設計圖開始,即PSD稿件:
移動端PSD稿件的尺寸確定較之PC端的PSD稿件不一樣,具體體如今設計圖的尺寸上,如今移動端的設計圖尺寸大多以iPhone5和iPhone6的設備像素尺寸做爲依據,好比拿到一張PSD設計圖,它的總寬度爲640px(iPhone5)或者750px(iPhone6)。本例就拿iPhone6的設計圖尺寸爲標準進行講解,其它設計圖尺寸道理是同樣的,這並不影響咱們的開發。css
首先咱們要有一張設計圖才行,看下圖,假設咱們有一張設計圖,它很簡單,只有一個紅色的方塊:html
拿到了設計圖,因而你開開心心的開始寫代碼了,你打開了編輯器,並寫下了以下HTML代碼:java
<!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" /> </head> <body> <div class="box"></div> </body> </html>
HTML代碼寫好了,你用了一個帶有box類的div標籤做爲ps稿中的紅色塊,通過尺寸測量,你爲上面代碼添加了CSS樣式,最後你的代碼是這樣的:瀏覽器
<!DOCTYPE html> <html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <div class="box"></div> </body> </html>
上面的代碼中,你只是在原來的基礎上增長了CSS樣式,首先你清除了body標籤上的默認樣式,這個沒什麼好說的,而後你根據設計圖中測量的尺寸來給box編寫樣式,寬200px;高200px;背景紅色。看上去並無什麼問題,因而你開開心心的打開瀏覽器,刷新頁面,你的臉色沉了下來,由於你看到了你不想看到的結果,以下圖,上圖爲設計稿的樣式,下圖爲你編寫的html文件的樣式:iphone
經過對比psd原稿和咱們目前所寫的html頁面,能夠看出咱們html頁面的問題,紅色方塊與整個頁面的比例和psd原稿不同啊,那麼爲何咱們明明是按照原稿測量的尺寸寫出來的代碼卻和psd原稿顯示的效果不同呢?別忘了,psd原稿的尺寸是按照設備像素設計的,因爲咱們所用的設計稿是基於iPhone6設計的,因此咱們設計稿的尺寸就是iPhone6的設備像素的尺寸,也就是750px,而咱們CSS中的樣式是基於佈局視口的尺寸計算的,因爲咱們html頁面中因爲寫入瞭如下meta標籤:編輯器
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
在上一篇咱們講過, width=device-width 這段代碼是讓佈局視口的尺寸等於理想視口。
根據公式(縮放比例爲1):
設備像素比(DPR) = 設備像素個數 / 理想視口像素個數(device-width)
由於iPhone6的DPR(設備像素比)爲2,設備像素爲750,因此iPhone6的理想視口尺寸爲375px。因此上面代碼最終致使的是:使咱們佈局視口的寬度變成了375px。而咱們CSS中編寫的樣式尺寸又是基於佈局視口計算的,因此咱們獲得的頁面看上去比例不對,以下圖:佈局
如上面兩幅圖片,咱們知道,psd稿的總寬是750px,元素寬200px,而咱們真正作頁面的時候,佈局視口的寬度是375px,正好是設計稿的一半。因此咱們不能直接使用設計稿上面測量所得的像素尺寸,根據比例,咱們應該將測量所得的尺寸除以2,纔是咱們CSS中佈局所用的尺寸,據此,咱們將200px除以2獲得100px,因而咱們修改代碼,將紅色方塊的寬高都設爲100px,刷新頁面,看看比例是否是和設計圖同樣了?答案是確定的,以下圖爲修改後的html頁面:字體
這樣,咱們就獲得了正確的數據,而且正確的寫出了頁面,你很高興,但是問題來了,若是你在作頁面的時候,測量了一個元素的寬度,寬度是一個奇數,好比111像素,按照咱們以前的作法是,將測量到的數據除以2,獲得咱們真正使用的數據,因此111除以2等於55.5px,咱們知道,計算機(手機)沒辦法顯示不到一個像素的像素值,計算機(手機)會自動將其補全爲一個像素進行顯示,因此最終會將元素顯示爲56像素,這並非咱們想要的結果。
另外,咱們的設計稿是基於iphone6設計的,咱們調試頁面也是在iphone6下調試的。又由於iphone6的設備像素比試2,因此咱們才能由設計稿測量的數據除以2後直接使用,而且在iphone6下沒有問題,可是你要知道,並非全部手機的設備像素比都是2,有的手機的設備像素比試2.5或者3。而且不一樣設備的設備像素又不一樣,這樣就致使理想視口的尺寸不一樣,從而致使佈局視口的尺寸不一樣,那麼咱們直接根據iphone6的設計稿尺寸除以2獲得的尺寸用來編寫CSS是不能在全部設備下無缺顯示的。ui
因此,咱們要換一個方法。
因而咱們想到:若是咱們能將佈局視口的尺寸設置爲和設備像素尺寸相等的話,這樣咱們就保證了設計圖與頁面的1:1關係,那麼咱們就能夠直接使用psd中測量的尺寸了,而後在其餘尺寸的手機中,咱們進行等比縮放就ok了。那麼如何才能讓佈局視口的尺寸等於設備像素尺寸呢?
咱們注意到meta標籤中的 width=device-width 這段代碼,首先你要明白這句話的意思,前面講過,這句話最終致使的結果是:讓佈局視口的尺寸等於理想視口的尺寸。言外之意就是,在代碼 width=device-width 中:
width:是佈局視口的width
device-width:是理想視口的寬度
根據公式(縮放比例爲1):
設備像素比(DPR) = 設備像素個數 / 理想視口像素個數(device-width)
以iphone6爲例:
設備像素比(DPR):2
設備像素個數:750
因此在縮放比例爲1的狀況下,iphone6理想視口的像素個數爲 750 / 2 = 375,也就是說,對於iphone6來說 device-width的值爲375
因此咱們經過width=device-width這句話,間接的將佈局視口的尺寸設爲了375,也就是說,若是咱們能改變理想視口的尺寸,也就改變了佈局適口的尺寸,如何改變理想視口的尺寸呢?這就要講到縮放了,上一篇咱們講到過縮放,縮放是縮小或放大CSS像素的過程,以iphone6爲例,當咱們縮放比例爲1:1的時候,因爲iphone6的設備像素比爲2,因此iphone6的設備像素與CSS像素的關係看起來就像下圖這樣:
一個CSS像素寬度等於兩個設備像素寬度,因此750px的設備寬度的佈局視口爲357CSS像素。這是在縮放比例爲1的狀況下,既然縮放能夠放大或縮小CSS像素,因此若是咱們將CSS像素的寬度縮放至與設備像素寬度相等了,那麼750個設備像素也就能顯示750個CSS像素,縮放後的設備像素與CSS像素看起來應該像下圖這樣:
可是,咱們的縮放倍數是多少呢?在縮放比例爲1的時候,一個CSS像素的寬度 = 兩個設備像素的寬度,若是咱們想讓 一個CSS像素的寬度 = 一個設備像素的寬度,咱們就要將CSS像素縮小爲原來的0.5倍,實際上,咱們縮小的倍數 = 設備像素比的倒數。
因而,咱們修改上面的HTML代碼(修改了meta標籤):
<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=0.5,maximum-scale=0.5,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <div class="box"></div> </body> </html>
注意,上面代碼中咱們給紅色方塊使用的CSS尺寸直接使用的是psd稿中測量的尺寸,咱們刷新頁面,怎麼樣?滿意吧:
可是咱們這是有個前提的,那就是縮放0.5倍只適用於設備像素比爲2的設備(由於縮放值 = 1 / 設備像素比)。因此,爲了適應全部的設備,咱們應該用javascript代碼動態生成meta標籤:
var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
其中 window.devicePixelRatio 的值爲設備像素比。
因而咱們的代碼變成了這樣:
<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="" /> <style> body{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <div class="box"></div> <script> var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); </script> </body> </html>
上面的代碼最終能保證一個問題,那就是不管任何設備,佈局視口的寬度老是等於設備像素。
這樣,咱們在設計圖中測量爲200px的寬度就能直接用在CSS中了,而且在iphone6中顯示無缺,但是別忘了,咱們的設計圖就是根據iphone6設計的,若是換作其餘設備,還能顯示無缺麼?咱們不妨試一下,以下圖,是上面代碼在iphone5和iphone6下的對比:
咱們發現,不管是五仍是6,即便設備像素變了,即屏幕寬度變了,但是紅色方塊的寬度並無變,這並非一個好的現象,由於這樣頁面的元素就不成比例了,會影響到佈局,因此咱們要想辦法讓咱們頁面的元素跟着設備變化而等比縮放,這就是咱們要解決的第二個問題,怎麼實現呢?這就要講到rem的知識點了。
什麼是rem?
rem是相對尺寸單位,相對於html標籤字體大小的單位,舉個例子:
若是html的font-size = 18px;
那麼1rem = 18px,須要記住的是,rem是基於html標籤的字體大小的。
相信你已經明白了,對沒錯,咱們要把以前用px作元素尺寸的單位換成rem,因此,如今的問題就是若是轉換,由於rem是根據html標籤的font-size值肯定的,因此咱們只要肯定html標籤的font-size值就好了,咱們首先本身定一個標準,就是讓font-size的值等於設備像素的十分之一,即:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
以iphone6爲例,html標籤的font-size的值就等於 750 / 10 = 75px 了,這樣 1rem = 75px,因此紅色方塊200px換算爲rem單位就是 200 / 75 = 2.6666667rem。
那麼在iphone5中呢?由於iphone5的設備像素爲640,因此iphone的html標籤的font-size的值爲 640 / 10 = 64px,因此 1rem = 64px,因此在iphone6中顯示爲200px的元素在iphone5中會顯示爲 2.6666667 * 64 像素,這樣,在不一樣設備中就實現了讓元素等比縮放從而不影響佈局。而上面的方法也是手機淘寶所用的方法。因此,如今你只須要將你測量的尺寸數據除以75就轉換成了rem單位,若是是iPhone5就要除以64,即除以你動態設置的font-size的值。
另外須要注意的是:作頁面的時候文字字體大小不要用rem換算,仍是使用px作單位。後面會講到。
讓咱們來總結一下咱們如今瞭解的方法:
一、將佈局視口大小設爲設備像素尺寸:
var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
二、動態設置html字體大小:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
三、將設計圖中的尺寸換算成rem
元素的rem尺寸 = 元素的psd稿測量的像素尺寸 / 動態設置的html標籤的font-size值
說了一大堆,其實咱們使用下面的html莫板就能夠寫頁面了,惟一須要你作的就是計算元素的rem尺寸,因此即便你沒看懂上面的講述也不重要,你只要將莫板拿過去用就行了:
<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="" /> </head> <body> <script> var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px'; </script> </body> </html>
如今咱們使用上面的方法修改咱們的代碼以下:
<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="" /> <style> body{ margin: 0; padding: 0; } .box{ width: 2.66666667rem; height: 2.66666667rem; background: red; } </style> </head> <body> <div class="box"></div> <script> var scale = 1 / window.devicePixelRatio; document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px'; </script> </body> </html>
打開瀏覽器,分別在iPhone6和iPhone5下查看頁面,咱們會發現,如今的元素能夠根據手機的尺寸不一樣而等比縮放了。
上面的方法是手機淘寶的方法,有一個缺點,就是轉化rem單位的時候,須要除以font-size的值,淘寶用的是iPhone6的設計圖,因此淘寶轉換尺寸的時候要除以75,這個值可很差算,因此還要借用計算器來完成,影響開發效率,另外,在轉還rem單位時遇到除不盡的數時咱們會採用很長的近似值好比上面的2.6666667rem,這樣可能會使頁面元素的尺寸有誤差。
除了上面的方法比較通用以外,還有一種方式,咱們來從新思考一下:
上面作頁面的思路是:拿到設計圖,好比iPhone6的設計圖,咱們就將瀏覽器設置到iPhone6設備調試,而後使用js動態修改meta標籤,使佈局視口的尺寸等於設計圖尺寸,也就是設備像素尺寸,而後使用rem替代px作尺寸代爲,使得頁面在不一樣設備中等比縮放。
如今假如咱們不去修改meta標籤,正常使用縮放爲1:1的meta標籤,即便用以下meta標籤:
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" />
還以iPhone6爲例,咱們知道,在縮放爲1:1的狀況下,根據公式:
設備像素比(DPR) = 設備像素個數 / 理想視口像素個數(device-width)
咱們知道:
設備像素 = 設計圖尺寸 = 750px
佈局視口 = 375px
假設咱們以iPhone6設計圖尺寸爲標準,在設計圖的尺寸下設置一個font-size值爲100px。
也就是說:750px寬的頁面,咱們設置100px的font-size值,那麼頁面的寬度換算爲rem就等於 750 / 100 = 7.5rem。
咱們就以頁面總寬爲7.5rem爲標準,那麼在佈局視口中,也就是頁面總寬爲375px下,font-size值應該是多少?很簡單:
font-size = 375 / 7.5 = 50px
那麼在iPhone5下呢?由於iPhone5的佈局視口寬爲320px,因此若是頁面總寬以7.5爲標準,那麼iPhone5下咱們設置的font-size值應該是:
font-size = 320 / 7.5 =42.666666667px
也就是說,無論在什麼設備下,咱們均可以把頁面的總寬度設爲一個以rem爲單位的定值,好比本例就是7.5rem,只不過,咱們須要根據佈局視口的尺寸動態設置font-size的值:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
這樣,不管在什麼設備下,咱們頁面的總寬度都是7.5rem,因此咱們直接在設計圖上測量px單位的尺寸,而後除以100轉換成rem單位後直接使用就能夠了,好比,在iPhone6設計圖中測量一個元素的尺寸爲200px,那麼轉換成rem單位就是 200 / 100 = 2rem,由於在不一樣設備下咱們動態設置了html標籤的font-size值,因此不一樣設備下相同的rem值對應的像素值是不一樣的,這樣就實現了在不一樣設備下等比縮放。咱們修改html代碼以下:
<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" /> <style> body{ margin: 0; padding: 0; } .box{ width: 2rem; height: 2rem; background: red; } </style> </head> <body> <div class="box"></div> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; </script> </body> </html>
刷新頁面,分別在iPhone6和iPhone5下調試查看結果,會發現以下圖,使咱們想要的效果,等比縮放,ok,實際上這種作法也是網易的作法:
下面,咱們來總結一下第二種作法:
一、拿到設計圖,計算出頁面的總寬,爲了好計算,取100px的font-size,若是設計圖是iPhone6的那麼計算出的就是7.5rem,若是頁面是iPhone5的那麼計算出的結果就是6.4rem。
二、動態設置html標籤的font-size值:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 以rem爲單位的頁面總寬 + 'px';
如iPhone6的設計圖就是:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';
iPhone5的設計圖就是:
document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px';
三、作頁面是測量設計圖的px尺寸除以100獲得rem尺寸。
四、和淘寶的作法同樣,文字字體大小不要使用rem換算。
下面是這種作法的html莫板:
<html> <head> <title></title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px'; </script> </body> </html>
因爲這種作法在開發中換算rem單位的時候只須要將測量的尺寸除以100便可,因此不須要使用計算器咱們就能夠很快的完成計算轉換,因此這也會提高開發效率,本人也比較青睞這種作法。
另外,不管是第一種作法仍是第二種作法,咱們都提到了,文字字體大小是不要換算成rem作單位的,而是使用媒體查詢來進行動態設置,好比下面的代碼就是網易的代碼:
代碼片斷一:
@media screen and (max-width: 321px) { body { font-size:16px } } @media screen and (min-width: 321px) and (max-width:400px) { body { font-size:17px } } @media screen and (min-width: 400px) { body { font-size:19px } }
代碼片斷二:
@media screen and (max-width: 321px) { header,footer { font-size:16px } } @media screen and (min-width: 321px) and (max-width:400px) { header,footer { font-size:17px } } @media screen and (min-width: 400px) { header,footer { font-size:19px } }
咱們總結一下網易在文字字體大小上的作法,在媒體查詢階段,分爲三個等級分別是:
321px如下
321px - 400px之間
400px以上
具體文字大小要多少個像素這個以設計圖爲準,可是這三個等級之間是有規律的,仔細觀察發現,321px如下的屏幕字體大小比321px - 400px之間的屏幕字體大小要小一個像素,而321px - 400px之間的屏幕字體大小要比400以上屏幕字體大小要小2個像素。依照這個規律,咱們根據設計圖所在的像素區段先寫好該區段的字體大小,而後分別寫出另外兩個區段的字體大小媒體查詢代碼就能夠了。