說到移動端適配,首先咱們須要先搞清楚一些基礎知識,因此本文路線是先了解像素,dpr,視口等基礎知識,而後再整理出移動端適配方案。php
像素其實分爲兩種,分別是物理像素和CSS像素html
視口也叫做初始包含塊,之因此叫這個名字,是由於它包含了元素,它的寬度是全部CSS百分比寬度推算的根源。
在桌面瀏覽器,視口的寬度等同於瀏覽器窗口的寬度,高度即爲瀏覽器窗口的高度。但移動端就有點複雜了,移動端的視口分爲佈局視口和視覺視口。git
設置佈局視口寬度:<meta name="viewport" content="width=640"> 獲取佈局視口寬度:document.documentElement.clientWidth
佈局視口除了和meta設置的width有關,還和scale有關,scale後面會說。github
獲取視口寬度:window.innerWidth/Height
初始狀態下,通常視覺視口會等於佈局視口。web
實現方法:<meta name="viewport" content="width=device-width">(即設置佈局視口寬度爲設備寬度)
原理:能夠理解爲修改dppx,舉個例子,假設一屏幕DPR爲2,即1px對應2pt,若是這個時候,咱們設置scale=0.5,那麼dppx就會從2變成1,即1px對應1pt。因此,經過縮放咱們能夠調整本身所能控制的最小物理像素粒度。
縮放會影響佈局視口的大小,由於瀏覽器會盡可能讓佈局視口鋪滿屏幕,因此當咱們設置scale=0.5時,佈局視口的寬度會自動變爲原來的兩倍。
具體以下圖所示。
瀏覽器
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <script> console.log(document.documentElement.clientWidth); //結果爲375 </script>
<meta name="viewport" content="width=device-width,initial-scale=0.5"> <script> console.log(document.documentElement.clientWidth); //結果爲750 </script>
可能有人會問,scale的初始值是多少?其實這取決於viewport的寬度,由於瀏覽器會盡可能讓佈局視口鋪滿全屏,因此瀏覽器會根據佈局視口的大小動態調整scale的初始值大小,從而使佈局視口鋪滿全屏。
使用縮放的好處:對於DPR爲2或更高的屏幕,若是不作縮放操做,咱們所能控制的最小物理像素粒度是2pt或更多物理像素,這樣帶來了兩個問題。wordpress
<style> #log { border: 1px solid black; } </style> <div id="log"></div>
解決這兩個問題的方法就是縮放,咱們把scale設置爲1/dpr。佈局
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
這樣1px就對應1pt,咱們就能夠解決1px border問題和圖片的高清問題了。flex
<meta name="viewport" content="width=device-width,initial-scale=1">
適合場景:比較適合列表式的結構。優化
<meta name="viewport" content="width=640">
這個時候會發現,瀏覽器會幫助咱們將頁面鋪滿全屏,並且這是絕對的等比例縮放。圖片、文字等等全部元素都被縮放在手機屏幕中。
rem作寬度,viewport縮放
根據屏幕寬度設定rem值,須要適配的元素都使用rem爲單位,不須要適配的元素仍是使用 px 爲單位。
總共分兩步:
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
meta.setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no');
第二步是對頁面適配的優化,修改scale是爲了解決前面說到的1px border問題。
淘寶的Flexible使用的就是這種方案,並且它加了data-dpr屬性,這樣咱們就能夠根據不一樣的DPR設置不一樣的樣式。
方案一比較適合列表這種比較固定的結構,方案二適合的場景比較多,並且實現簡單,但須要注意它會將頁面的全部元素都縮放,方案三適合的場景是頁面內有些元素須要適配,有些元素不須要適配。整體來說,方案二和方案三是比較經常使用的方式。
參考文獻:
https://www.zybuluo.com/gongzhen/note/170557
鄭航的知乎回答https://www.zhihu.com/question/35221839
https://github.com/amfe/article/issues/17
https://github.com/riskers/blog/issues/18
https://riskers.github.io/share/share/flexible.htm#1
https://github.com/riskers/blog/issues/17
https://github.com/amfe/lib-flexible
http://www.html-js.com/article/2402
http://www.alloyteam.com/2016/03/mobile-web-adaptation-tool-rem/
https://www.nihaoshijie.com.cn/index.php/archives/593
http://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/