構建自適應的手機頁面

從事PC Web開發好多年,可是手機頁面開發較晚,因此最開始的時候,爲了作微信應用的開發,各類餓補,可是爲了將設計稿精準的適配在各類尺寸的手機上仍是太坑,因此找了些資料後,借鑑了一些成熟的網站,分享出來,歡迎拍磚。javascript

首先須要你對viewport有一個瞭解,建議看Apple官方文檔,雖然囉嗦,可是啃一遍,基本該明白的就全明白了。css

第一種方案

<meta name="viewport" content="target-densitydpi=device-dpi,width=640,user-scalable=no" />

簡便易行,適用狀況:html

  1. 網頁設計僅針對手機屏幕,而且沒有須要根據手機屏幕尺寸進行UI調整的內容,既沒有媒體查詢的CSSjava

  2. 產品層面能夠不考慮非主流設備或瀏覽器的兼容性,例如黑莓的某些設備或搜狗瀏覽器這類的不支持640定寬渲染的瀏覽器android

  3. 當手機橫豎切換時,可以容忍部分手機在橫屏瀏覽網頁時,可能出現的問題(潛在問題)。ios

這個方案是強制讓手機瀏覽器按640的比例來呈現網頁,讓瀏覽器去作尺寸適配;這個方案我以爲其實很是好,絕大多數的場景均可以支持,並且開發起來簡單高效,不須要考慮各類尺寸和樣式表的單位換算問題。git

這個方案有點相似css zoom,就是瀏覽器將整個網頁進行了縮放,注意一點:PC端的使用瀏覽器的開發工具進行縮放的時候,譬如使用iphone 5s 模式預覽,可能會有問題,好比border:1px的時候可能會不可見,字體會有些模糊等,可是手機端展示的時候不會出現這些問題,由於絕大多數手機目前屏幕分辨率都足夠高,並且專門針對viewport作了處理,因此這個問題能夠忽略。github

測試地址:點擊這裏,這個網頁就是按640定寬作的,能夠在多數尺寸的網頁上作適配gulp

第二種方案

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />

上面這個不用解釋了,絕大多數知名網站都這麼作的.
不少網站爲了可以讓圖片和字體也作自適應,會使用rem來做爲單位,而後再啓用javascript斷定屏幕寬度,動態改變html元素的fontsize。瀏覽器

爲了方便計算,一般會默認將html的font-size設置爲100px,這樣方便計算,例如你的網頁字體是16px,只須要寫成0.16rem就好了,而後假如設計稿是按640寬度設計,切圖的時候徹底按設計稿來進行單位換算,而後在js中獲取屏幕寬度,根據比例:100/x = 640/documentWidth 計算html的字體大小便可,固然要加入一個window.resize事件從新計算,以防橫豎屏切換。

重要:若是你但願字體不縮放,能夠不考慮將font-size設置爲rem

第二種方案有幾個弊端:

  1. 因爲背景圖片沒法作縮放,(background-size:cover|contain)只能針對單張圖片,而對於sprite css image無力解決,因此這裏要求若是有背景圖,所有制做成單張的,而後再加上background-size:cover|contain,這裏凸顯出使用css font的好處了...

  2. 頁面中的全部單位都須要用rem來計算,雖然 X/100是很簡單的計算,可是書寫的時候仍是讓人厭煩。

  3. 全部的圖片必須指定寬度,否則圖片會按原始寬度進行渲染,當屏幕尺寸與設計預期尺寸不一致時,就會出錯了。

根據上面的描述,我作了兩個工具:

  1. 製做時依然採用px做爲單位,經過watch插件監聽css文件的改變,而後動態轉換px2rem

  2. 根據圖片生成auto convert css icon文件,相似grunt-sprite,但只生成對應的css,而不合成圖片,這樣對於將以往的css sprite工具生成的圖片能夠低成本切換成單一圖片ICON 開發思路是這樣:

  3. 開發時區分目錄,例如src表示源碼,dest目錄標示轉換後的靜態文件,目前上規模的工程都這麼作,應該沒什麼成本了,而後css依然使用像素做爲單位。

  4. 經過grunt或gulp插件來監聽文件改變,而後作copy,sync之類的處理,同時這裏將css中的px按設定的比率轉換成rem。

  5. 不能在網頁中直接嵌入內聯style,或者須要自行轉換單位以後嵌入。

監聽腳本
(注:這裏假定開發的時候依據的寬度的640,默認字體是32像素)

// 根據屏幕寬度適配字體大小
$(window).on('resize', function () {
  var width = document.documentElement.clientWidth;
  $('html').css('font-size', (width / 640 * 32) + 'px');
}).triggerHandler('resize');

測試地址:點擊這裏

(由於個人工程使用的是grunt,因此寫的插件也是針對grunt的,若是你打算使用gulp,須要自行實現上面的工具了)

第三種方案

固定高度,寬度自適應

這個方案其實就是原生iphone的方案,既在不一樣尺寸的屏幕上顯示時,寬度會自適應,高度是固定的,字體大小也固定,譬如一個list元素的高度是44px,不管在iphone5,iphone6,iphone6+它都是44px高,可是寬度是不定的,這個實際上是一個標準實現方案,既高度肯定,內容寬度自適應,字體大小固定。

流行的大公司的H5網站基本都是這麼處理的,淘寶在這個方案的基礎上額外作了1px的適配,由於在視網膜雙倍屏上,實際上使用2px的物理像素來渲染1px的邏輯像素,爲了可以作到精準的1px,淘寶沒有默認寫viewport而是使用js來動態生成viewport。

固然dpr不一樣,生成的viewport也不同,雙倍屏的viewport是0.5, 3倍屏的是0.33333,全部單位使用rem,js根據不一樣的倍屏生成一個基礎的font-size,單倍屏幕是16px,雙倍是32px,3倍是48px,以此類推。

動態生成viewport額外引出兩個問題:
1.android的不少機型不支持動態生成的viewport,僅在IPHONE上適配良好,
2.原始的css不能再使用px,而要使用rem做爲單位。

第一個問題比較好解決,ua判斷好了,第二個問題須要在編寫css的時候動態轉換rem。

結合到一塊兒:

(新增):
因爲淘寶的方案比較複雜,爲了1PX的顯示作了很是複雜的處理,因此放棄了。有個折中的辦法是對1px的處理作scale縮放,不過這樣可能會在dpr爲1的屏幕出現問題,或者在dpr>2的屏幕依然會變粗。
不過這個方案簡單易行,事實上微信的UI團隊用的就這個方案,我參考了他們的解決辦法,實現了一套本身的UI:使用默認的1倍縮放viewport方案,不縮放圖片和字體,放棄自適應。1px問題採用scale方案解決。圖片佈局問題採用padding-top百分比寬度解決(能夠自行百度)

http://exui.legend.life
https://github.com/whosesmile...

總結

第一個定寬開發的方案其實很是適合小團隊作推廣頁面,由於這樣避免了各類工具的整合,下降了開發複雜度。

第二個方案適合須要適應絕大多數尺寸瀏覽器的項目,同時若是配置好打包工具,能夠很大程度下降難度,將開發和部署解耦,開發代碼比較清晰。

第三個方案適合對項目精細要求度比較高的,成本稍高。

相關文章
相關標籤/搜索