移動端自適應方案(轉載)

  • 真的須要動態生成viewport嗎?
  • 如何自適應?

而後給出主觀的最佳實踐。javascript

  • 最帥的flex

趕時間戳這裏傳送門css

比較無聊乾燥的文章,看前請喝水。html

研究樣本java

  1. 手淘 ml.js
  2. 天貓首頁
  3. 手機攜程

一個月前去了css開發者大會,聽到了手淘的自適應方案,想起以前一直就想了解ml.js到底幹了什麼事。回來仔細研究了一下,抱着好奇心一併看了一樣類型的網站的方案,深刻學習一下。瀏覽器

研究結論佈局

  1. 手淘學習

    • 獲取手機dpr(window.devicePixelRatio),動態生成viewport。測試

    • 換取手機寬度,分紅10份,每一份的寬度便是rem的尺寸。字體

    • 根據設計稿尺寸(px)經過計算,轉換成rem去佈局。flex

    ps:海外淘寶並無這樣作,而是scale1.0而且圖片大概都是2倍圖。

  2. 天貓

    • 採用scale=1.0 寫死viewport。

    • flex佈局,篤定認爲佈局尺寸是375 (iPhone6)

    • rem 肯定非flex的元素

  3. 手機攜程

    • 採用scale=1.0 寫死viewport

    • px + 百分比佈局

實現以前

說起實現以前,先簡單過一些概念。

完美視口

完美視口的概念已經街知巷聞了,若是不知道能夠先戳這裏。

在這幾篇文章裏,還會學會設備像素,css像素等概念,大神講的很透徹,這裏就不獻醜了。

ppk 談 viewport其1 ppk 談 viewport其2 ppk 談 viewport其3

這裏給出完美視口

<meta name="viewport" content="initial-scale=1.0,width=device-width,user-scalable=0,maximum-scale=1.0"/> 

在移動端,低端無定製的需求,均可以用這個完美視口完成。然而看到這篇文章的你,顯然完美視口還不能知足。

dpr

dpr是devicePixelRatio的簡寫,也就是屏幕分辯比

歷史緣由,因爲蘋果retina的產生,使得清晰度提高,主要是由於`設備像素`提高了一倍,所以能夠用更多像素去繪畫更清晰的圖像。#我亂說的#

坊間對於dpr更通俗的說法叫

  • 一倍屏
  • 兩倍屏
  • 三倍屏

scale

scale是屏幕拉伸比。也就是視口上的initial-scale , maximum-sacle 等屬性。

scale 和 dpr的關係是倒數。

直觀感覺

這是我對dpr的直觀感覺

一樣去展現 1 x 1 像素的點,雖然在屏幕上看到的大小是同樣,但背後表現它的像素數量是不一樣。

這也意味着,在同樣大小的面積內,更多物理像素的屏幕上展示色彩的能力越強。

但這不是我要關注的點,咱們關注的是。

1. 是否須要根據倍屏去切換scale達到伸縮的目的

2. 切換scale的成本和回報

下面根據幾個實驗來回答這兩個問題。

自適應問題

實驗1 - 傳說中的1px

大多數給出要動態切換scale的理由有如下兩個。

1. 1px並非 [ 真實的1px ] , 2. 爲了充分利用屏幕的分辨率,使用符合屏幕的圖片。 

真實的1px

這一條和設計稿密切想關,要討論它不能拋開設計稿不談。

這裏先補一下切圖課,若是本身要作1x , 2x, 3x 的設計稿。如何去實現?

尺寸!!!

大多數狀況下,設計師產出各類尺寸的稿子(事實上通常只是2倍稿子),都是先畫出大尺寸的稿子,再去縮小尺寸,最後導出。 這樣會帶來問題:

若是設計師在2倍稿子裏畫了一條1px的線,這時候假如咱們要在scale=1.0裏呈現的話,就會變成0.5px,以下圖。

而很大一部分手機是沒法畫出0.5px的,所以這裏通常有一個hack

transform:scaleX(0.5)或transform:scaleY(0.5) 

可是有人提出了, 既然能夠改變viewport的scale達到合理利用不一樣倍屏的優點,爲何不這麼寫呢。

<meta name="viewport" content="initial-scale=2.0,width=device-width/> 

等等,爲了設計稿的尺寸咱們如此大費周章?

 

事實上,即便2x設計稿避免了1px。3x設計稿也可能出現2px。

並且這裏若是寫死scale可能形成部分地方和稿子出入較大,沒法還原設計稿,界面的顯示會打折扣。

解決這個問題的關鍵在於:交流

  • 若是你的設計師是個要求嚴格,並且產品界面把控很是嚴格的話,應該動態去實現viewport或使用scale的hack去改變。

  • 若是部分區域實在沒有必要[ 過分優化 ], scale=1.0 實在是很是低成本還原的方案,何嘗不可。

對應倍圖

對於這一點,爭議較多,由於若是要作到對應倍圖的話,意味着圖片都須要作三份。成本過高了。

這裏一般有兩種作法

  1. 圖片服務

    例如在100x100的圖片容器中。

    1倍圖 http:// img.xxx.com/abc.jpg_100x100 2倍圖 http:// img.xxx.com/abc.jpg_200x200 3倍圖 http:// img.xxx.com/abc.jpg_300x300 
  2. 定死尺寸

    放棄1屏手機,所有啓用2倍圖,因爲流量會消耗比較大(低端機),所以滾動加載等優化手段就會顯得比較重要了。

實驗1 - scale對倍圖重要嗎

這裏看一下不一樣scale下圖片的差別。

  • 測試樣本:160x160凱爾特人隊標logo(一不當心暴露了綠色的血液)

  • 測試容器:160x160 img標籤

  • 測試環境: intial-scale分別爲1.0 / 0.5 / 0.3333

  • 圖片尺寸: 1x(160x160) 2x(320x320) 3x(480x480)

    測試結論:不一樣scale下使用不一樣圖片差別很是大。

    可是這裏須要驗證,是否不一樣scale同一圖片差別起到絕對做用。

    肉眼觀看基本無區別,除了用取色器去獲取,會發現有色差和部分像素被分割(下面會說到),以外,用不一樣scale顯示同一圖片基本沒有什麼區別。

實驗2 - DownSampling

因爲上一個實驗最後的圖片,使用同一scale下,不一樣倍數的圖片,存在色差,這裏驗證一下。

  • 測試方案

    測試圖片:

    圖片尺寸: 400x300 , 300x225 , 200x150 , 100x75

    測試環境: scale = 1.0

    測試容器: 100x75的 img元素

    因爲以前知道了DownSampling概念的存在,這裏只是好奇心驅動試驗一下。(對自適應其實沒有卵用)

    DownSampling是說大圖放入比圖片尺寸小的容器中的時候,出現像素分割成就近色的狀況。

     

    測試結果:

    注:6plus貌似和其餘機型不一樣。

    觸發狀況: 不一樣顏色像素接觸的地方,會出現DownSampling。

rem

對於rem要說的很少,看這張圖。對於用到px的元素,使用rem統一去管理是很靈活的!(這裏原諒我盜圖了..)

字體

不管是採用動態生成viewport或者寫死scale,字體都須要適配大屏。以前提出的rem方案被證明在不一樣手機上顯示不一致,這裏仍是迴歸成了px。

px最好用雙數

 

兩種方案(這裏不考慮媒體查詢,由於Android碎..,嗯,不說了...)

  1. JS動態計算(常見作法)

    根據不一樣屏幕寬度計算不一樣字號大小。
    
    
    1. 定基準值,設計稿是750寬度(2倍屏),字體的大小是24px. 2. 計算指定寬度的字體大小。 var fontSize = width / 750 * 24 ; 
  2. 根據dpr設定 (比較好的作法)

    ps : 通常時初始化時設置爲根元素html的attribute,

    window.document.documentElement.setAttribute('dpr',window.devicePixelRatio) 

    而後css這樣寫

    [dpr=1] { font-size=16px; } [dpr=2] { font-size=32px; } 

佈局

權衡之下,我以爲flex真的靈活方便太多,所以這裏給出一個佈局demo。大體以下圖。(畫的比較粗糙..)

(左稿右還原)

基本涵蓋:

  • 固定頭部
  • 固定底部
  • 多列自適應
  • 高度自定義
  • 內容滾動

爲何flex可以作到百分比作不到的自適應。

好比咱們也去學天貓,篤定認爲寬度就是375(iPhone6尺寸),那麼兩個元素flex分別爲200和175。

無需計算百分比,在不一樣的界面上就會自動計算,並且以該瀏覽器能夠識別的最小單位實現,比本身計算的百分比要精準。

demo傳送門

結論

  1. 寫死initial-scale=1.0 對於實現1px問題, 問題比較大。與設計師溝通協商纔是最好的解決問題的方法。

  2. 寫死initial-scale=1.0 對於不一樣圖片的顯示, 採用不一樣倍圖的話,會有必定壓縮,但在可接受範圍內。(固然,動態生成scale可以完美呈現...)

  3. 佈局

    若是採用動態生成viewport方案,就用到rem來還原設計稿(還有rem-px的計算)。成本在效率上。

    若是採用寫死initial-scale=1.0方案,就用flex佈局,主要成本在flex兼容性上,可是實現很是靈活簡單。

後記

viewport的scale的重要性遠比我想象的要低不少,我本來覺得這就是自適應。

可是後來發現,其實自適應仍是回到了遠古時代的百分比%,只是如今有更聰明更靈活的方式flex,將來應該有兩個方向去自適應。

  • 一個是擁抱vw,vh。(手淘的ml.js十等分寬度,1rem=10vw

  • 一個是更好的使用flex

如今使用後者已經有不少的庫能夠解決兼容性了,如參考資源最後的一個flex庫。

調研的網站並很少,可是百分比仍然是不少人的首選。

相關文章
相關標籤/搜索