弱弱插個我們團隊的招聘:http:///RLVSDvP
前方依舊高能 ^_^ , 本文主要解決以下問題:
- 真的需要動態(tài)生成viewport嗎?
- 如何自適應?
然后給出主觀的最佳實踐。
趕時間戳這里傳送門
比較無聊干燥的文章,看前請喝水。
研究樣本
- 手淘
ml.js
- 天貓首頁
- 手機攜程
一個月前去了css開發(fā)者大會,聽到了手淘的自適應方案,想起之前一直就想了解ml.js到底干了什么事?;貋碜屑氀芯苛艘幌?,抱著好奇心一并看了同樣類型的網站的方案,深入學習一下。
研究結論
手淘
獲取手機dpr(window.devicePixelRatio ),動態(tài)生成viewport。
換取手機寬度,分成10份,每一份的寬度即是rem的尺寸。
根據設計稿尺寸(px )通過計算,轉換成rem 去布局。
ps :海外淘寶并沒有這樣做,而是scale1.0并且圖片大概 都是2倍圖。
天貓
手機攜程
采用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
大多數給出要動態(tài)切換scale的理由有以下兩個。
1. 1px并不是 [ 真實的1px ] ,
2. 為了充分利用屏幕的分辨率,使用符合屏幕的圖片。
真實的1px
這一條和設計稿密切想關,要討論它不能拋開設計稿不談。
這里先補一下切圖課 ,如果自己要做1x , 2x, 3x 的設計稿。如何去實現?
尺寸?。。?/p>
大多數情況下,設計師產出各種尺寸的稿子(事實上一般只是2倍稿子),都是先畫出大尺寸的稿子,再去縮小尺寸,最后導出。
這樣會帶來問題:
如果設計師在2倍稿子里畫了一條1px 的線,這時候假如我們要在scale=1.0里呈現的話,就會變成0.5px ,如下圖。
而很大一部分手機是無法畫出0.5px的,因此這里一般有一個hack
transform:scaleX(0.5)或transform:scaleY(0.5)
但是有人提出了, 既然可以改變viewport的scale達到合理利用不同倍屏的優(yōu)勢,為什么不這么寫呢。
<meta name="viewport" content="initial-scale=2.0,width=device-width/>
等等,為了設計稿的尺寸我們如此大費周章?
事實上,即使2x設計稿避免了1px。3x設計稿也可能出現2px。
而且這里如果寫死scale可能造成部分地方和稿子出入較大,無法還原設計稿,界面的顯示會打折扣。
解決這個問題的關鍵在于:交流
如果你的設計師是個要求嚴格,而且產品界面把控非常嚴格的話,應該動態(tài)去實現viewport或使用scale的hack去改變。
如果部分區(qū)域實在沒有必要[ 過度優(yōu)化 ] , 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倍圖,由于流量會消耗比較大(低端機),因此滾動加載 等優(yōu)化手段就會顯得比較重要了。
實驗1 - scale對倍圖重要嗎
這里看一下不同scale下圖片的差異。
測試樣本:160x160凱爾特人隊標logo(一不小心暴露了綠色的血液)
測試容器:160x160 img標簽
測試環(huán)境: intial-scale分別為1.0 / 0.5 / 0.3333
圖片尺寸: 1x (160x160) 2x (320x320) 3x (480x480)
測試結論:不同scale 下使用不同圖片 差異非常大。
但是這里需要驗證,是否不同scale 對同一圖片 差異起到絕對作用。
肉眼觀看基本無區(qū)別 ,除了用取色器去獲取,會發(fā)現有色差 和部分像素被分割(下面會說到),之外,用不同scale顯示同一圖片基本沒有什么區(qū)別。
實驗2 - DownSampling
由于上一個實驗最后的圖片,使用同一scale下,不同倍數的圖片,存在色差,這里驗證一下。
測試方案
測試圖片:
圖片尺寸: 400x300 , 300x225 , 200x150 , 100x75
測試環(huán)境: scale = 1.0
測試容器: 100x75的 img元素
由于之前知道了DownSampling概念的存在,這里只是好奇心驅動試驗一下。(對自適應其實沒有卵用)
DownSampling是說大圖放入比圖片尺寸小的容器中的時候,出現像素分割成就近色的情況。
測試結果:
注:6plus貌似和其他機型不同。
觸發(fā)情況: 不同顏色像素接觸的地方,會出現DownSampling。
rem
對于rem要說的不多,看這張圖。對于用到px的元素,使用rem統(tǒng)一去管理是很靈活的!(這里原諒我盜圖了..)
字體
無論是采用動態(tài)生成viewport或者寫死scale,字體都需要適配大屏。之前提出的rem方案被證實在不同手機上顯示不一致,這里還是回歸成了px。
px最好用雙數
兩種方案(這里不考慮媒體查詢,因為Android碎..,嗯,不說了...)
JS動態(tài)計算(常見做法)
根據不同屏幕寬度計算不同字號大小。
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。
無需計算百分比,在不同的界面上就會自動計算,而且以該瀏覽器可以識別的最小單位實現,比自己計算的百分比要精準。
demo傳送門
結論
寫死initial-scale=1.0 對于實現1px問題 , 問題比較大。與設計師溝通協商 才是最好的解決問題的方法。
寫死initial-scale=1.0 對于不同圖片的顯示, 采用不同倍圖的話,會有一定壓縮,但在可接受范圍內。(當然,動態(tài)生成scale能夠完美呈現...)
布局
如果采用動態(tài)生成viewport 方案,就用到rem來還原設計稿(還有rem-px的計算)。成本在效率 上。
如果采用寫死initial-scale=1.0 方案,就用flex布局,主要成本在flex兼容性 上,但是實現非常靈活簡單。
后記
viewport的scale 的重要性遠比我想象的要低很多,我原本以為這就是自適應。
但是后來發(fā)現,其實自適應還是回到了遠古時代的百分比% ,只是現在有更聰明更靈活的方式flex ,未來應該有兩個方向去自適應。
現在使用后者已經有很多的庫可以解決兼容性了,如參考資源最后的一個flex庫。
調研的網站并不多,但是百分比仍然是很多人的首選。
|