移動端自適應方案
前方依舊高能 ^_^ , 本文主要解決以下問題:
- 真的需要動態生成viewport嗎?
- 如何 自適應 ?
然后給出主觀的最佳實踐。
- 最帥的flex
趕時間戳這里傳送門
比較無聊干燥的文章,看前請喝水。
研究樣本
- 手淘ml.JS
- 天貓首頁
- 手機攜程
一個月前去了css開發者大會,聽到了手淘的自適應方案,想起之前一直就想了解ml. js 到底干了什么事。回來仔細研究了一下,抱著好奇心一并看了同樣類型的網站的方案,深入學習一下。
研究結論
- 手淘
- 獲取手機dpr(window.devicePixelRatio),動態生成viewport。
- 換取手機寬度,分成10份,每一份的寬度即是rem的尺寸。
- 根據設計稿尺寸(px)通過計算,轉換成rem去布局。
ps:海外淘寶并沒有這樣做,而是scale1.0并且圖片大概都是2倍圖。
- 天貓
- 采用scale=1.0寫死viewport。
- flex布局,篤定認為布局尺寸是375 (iPhone6)
- rem 確定非flex的元素
- 手機攜程
- 采用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像素的點,雖然在屏幕上看到的大小是一樣,但背后表現它的像素數量是不同。
這也意味著,在一樣大小的面積內,更多物理像素的屏幕上展現色彩的能力越強。
但這不是我要關注的點,我們關注的是。
<span>1</span><span>.</span> 是否需要根據倍屏去切換scale達到伸縮的目的
<span>2</span><span>.</span> 切換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 實在是非常低成本還原的方案,未嘗不可。
對應倍圖
對于這一點,爭議較多,因為如果要做到對應倍圖的話,意味著圖片都需要做三份。成本太高了。
這里通常有兩種做法
- 圖片服務例如在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
- 定死尺寸放棄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是說大圖放入比圖片尺寸小的容器中的時候,出現像素分割成就近色的情況。
測試結果<span>:</span>
注:6plus貌似和其他機型不同。
觸發情況:不同顏色像素接觸的地方,會出現DownSampling。
rem
對于rem要說的不多,看這張圖。對于用到px的元素,使用rem統一去管理是很靈活的!(這里原諒我盜圖了..)
字體
無論是采用動態生成viewport或者寫死scale,字體都需要適配大屏。之前提出的rem方案被證實在不同手機上顯示不一致,這里還是回歸成了px。
px最好用雙數
兩種方案(這里不考慮媒體查詢,因為 Android 碎..,嗯,不說了...)
- JS動態計算(常見做法)
根據不同屏幕寬度計算不同字號大小。 1. 定基準值,設計稿是750寬度(2倍屏),字體的大小是24px. 2. 計算指定寬度的字體大小。 var fontSize = width / 750 * 24 ;
- 根據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。
無需計算百分比,在不同的界面上就會自動計算,而且以該瀏覽器可以識別的最小單位實現,比自己計算的百分比要精準。
結論
- 寫死initial-scale=1.0對于實現1px問題, 問題比較大。與設計師溝通協商才是最好的解決問題的方法。
- 寫死initial-scale=1.0對于不同圖片的顯示, 采用不同倍圖的話,會有一定壓縮,但在可接受范圍內。(當然,動態生成scale能夠完美呈現...)
- 布局如果采用動態生成viewport方案,就用到rem來還原設計稿(還有rem-px的計算)。成本在效率上。
如果采用寫死initial-scale=1.0方案,就用flex布局,主要成本在flex兼容性上,但是實現非常靈活簡單。
后記
viewport的scale的重要性遠比我想象的要低很多,我原本以為這就是自適應。
但是后來發現,其實自適應還是回到了遠古時代的百分比%,只是現在有更聰明更靈活的方式flex,未來應該有兩個方向去自適應。
- 一個是擁抱vw,vh。(手淘的ml.js十等分寬度,1rem=10vw)
- 一個是更好的使用flex
現在使用后者已經有很多的庫可以解決兼容性了,如參考資源最后的一個flex庫。
調研的網站并不多,但是百分比仍然是很多人的首選。
參考資源
flex方案 適配到IE10+
原文 http://caibaojian.com/mobile-responsive-demo.html