開發移動端頁面的頁面尺寸適配

之前寫了一篇文章《一篇真正教會你開發移動端一面的文章(一)》。那是本篇文章的基礎,如果沒有閱讀過的同學可以去看看,今天就給大家帶來乾貨,真真正正的講到如何很好的開發一個移動端的頁面



好了,讓我們開始吧,從哪裏開始呢?從設計圖開始,即PSD稿件:移動端PSD稿件的尺寸肯定較之PC端的PSD稿件不同,具體體現在設計圖的尺寸上,現在移動端的設計圖尺寸大多以iPhone5和iPhone6的設備像素尺寸作爲依據,比如拿到一張PSD設計圖,它的總寬度爲640px(iPhone5)或者750px(iPhone6)。本例就拿iPhone6的設計圖尺寸爲標準進行講解,其它設計圖尺寸道理是一樣的,這並不影響我們的開發。


首先我們要有一張設計圖才行,看下圖,假設我們有一張設計圖,它很簡單,只有一個紅色的方塊:



拿到了設計圖,於是你開開心心的開始寫代碼了,你打開了編輯器,並寫下了如下HTML代碼:


<!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文件的樣式:



通過對比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是不能在所有設備下完好顯示的。


所以,我們要換一個方法。


於是我們想到:如果我們能將佈局視口的尺寸設置爲和設備像素尺寸相等的話,這樣我們就保證了設計圖與頁面的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?


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做單位。後面會講到。


讓我們來總結一下我們現在瞭解的方法:


1、將佈局視口大小設爲設備像素尺寸:


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');


2、動態設置html字體大小:


document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';


3、將設計圖中的尺寸換算成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,實際上這種做法也是網易的做法:




下面,我們來總結一下第二種做法:


1、拿到設計圖,計算出頁面的總寬,爲了好計算,取100px的font-size,如果設計圖是iPhone6的那麼計算出的就是7.5rem,如果頁面是iPhone5的那麼計算出的結果就是6.4rem。


2、動態設置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';


3、做頁面是測量設計圖的px尺寸除以100得到rem尺寸。

4、和淘寶的做法一樣,文字字體大小不要使用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>


由於這種做法在開發中換算rem單位的時候只需要將測量的尺寸除以100即可,所以不需要使用計算器我們就可以很快的完成計算轉換,所以這也會提升開發效率,本人也比較青睞這種做法。


另外,無論是第一種做法還是第二種做法,我們都提到了,文字字體大小是不要換算成rem做單位的,而是使用媒體查詢來進行動態設置,比如下面的代碼就是網易的代碼:


代碼片段一:


@media screen and (max-width321px) {

    body {

        font-size:16px

    }

}

 

@media screen and (min-width321px) and (max-width:400px) {

    body {

        font-size:17px

    }

}

 

@media screen and (min-width400px) {

    body {

        font-size:19px

    }

}


代碼片段二:


@media screen and (max-width321px) {

    header,footer {

        font-size:16px

    }

}

 

@media screen and (min-width321px) and (max-width:400px) {

    header,footer {

        font-size:17px

    }

}

 

@media screen and (min-width400px) {

    header,footer {

        font-size:19px

    }

}


我們總結一下網易在文字字體大小上的做法,在媒體查詢階段,分爲三個等級分別是:


321px以下

321px – 400px之間

400px以上


具體文字大小要多少個像素這個以設計圖爲準,但是這三個等級之間是有規律的,仔細觀察發現,321px以下的屏幕字體大小比321px – 400px之間的屏幕字體大小要小一個像素,而321px – 400px之間的屏幕字體大小要比400以上屏幕字體大小要小2個像素。依照這個規律,我們根據設計圖所在的像素區段先寫好該區段的字體大小,然後分別寫出另外兩個區段的字體大小媒體查詢代碼就可以了。


終於碼完了這第二篇文章,無力再多說其他的話,望對大家有幫助,有些細節地方沒有細說,另外作者水平有限,希望大家指正共同進步,謝謝。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章