1. viewport影響着我們頁面的什麼?
viewport是虛拟顯示視口,它是時刻存在的【這一點有異議,有的人說必須要設定meta标簽才會存在viewport,然而在chrome浏覽器的調試工具中,添加和不添加meta标簽都會觸發viewport的行為】,我們設定meta标簽隻是去改變viewport的相關屬性,并非是去設定一個viewport。隻是在響應式頁面開發過程中,預設的viewport會造成我們頁面觀感不合适,是以要去設定預設的縮放比例,以及viewport預設寬度,來适應響應式的開發。
關于虛拟視窗,MDN上做了如下解釋:
窄螢幕裝置(如移動裝置)在一個虛拟視窗或視口中渲染頁面,這個視窗或視口通常比螢幕寬;然後縮小渲染的結果,以便在一屏内顯示所有内容。然後使用者可以移動、縮放以檢視頁面的不同區域。例如,如果移動螢幕的寬度為640px,則可能會用980px的虛拟視口渲染頁面,然後縮小頁面以适應640px的視窗大小。
總結一下,當一個頁面将要展示到我們的手機上時,頁面會先在viewport中渲染,假如說我們沒有設定viewport的寬度,頁面會按照預設的980px的寬度去渲染(想象一下把你的浏覽器視窗縮小為980px的寬度,你所看到的效果就是viewport中的渲染效果),然後渲染好的頁面會被縮放顯示到我們的裝置上(想象一下把你縮小為寬度為980px的浏覽器上的畫面,塞到你的手機中)。
我們來看一組示例(預設viewport):
<style>
.topbar {width: 100%;height: 200px;background-color: pink;}
.container{width: 300px;height: 300px;background-color: skyblue;margin: 0 auto;}
</style>
<body>
<div class="topbar"></div>
<div class="container"></div>
</body>

看起來布局上似乎很完美,但當我們添加上文字後,在我們的手機上就會這樣顯示:
文字内容簡直小的可憐,這就是為什麼我們不願意去使用預設的viewport:他會無視我們手中實際裝置的寬度去按照960px的寬度渲染頁面,然後将渲染好的頁面進行縮放再塞入我們的手機顯示器,導緻頁面被縮放的過小。假入我們此時規定viewport的寬度與裝置寬度相等,如下加入meta标簽:
對于iPhoneSE來說,它的寬度為320px,那麼viewport就以320px的寬度去渲染頁面而非980px,之後渲染好的頁面就不會被縮放,而是直接顯示在我們的手機上,如下效果:
當然,我們也能看出,我們再下方定義的固定寬高的div,也同樣會被縮放,這就是為什麼我們推薦在響應式開發中使用半分比寬度而非絕對寬度,這會導緻元素的縮放不合理,當有元素超過我們的viewport寬度後,viewport機制就會錯亂,分為以下兩種情況(針對Chrome和最新的Android Webview):
- 如果我們設定了viewport,此時固定元素寬度如果大于設定的viewport寬度,viewport的寬度會回變化為頁面最寬的元素,來顯示過寬的元素,但是如果寬度設定為100%的元素,寬度仍保持原有的viewport寬度。
- 當最寬的元素寬度大于980px(或者我們設定的最大viewport寬度),就會出現橫向滾動條來顯示我們頁面中最寬的元素。
2. 什麼像素比和實體像素?
像素比(dpr) = 實體像素 / css像素
通過
window.devicePixelRatio
獲得目前裝置的DPR
如:iPhoneX的DPR為3,iPhone5 Se的DPR為2,正常顯示器的DPR為1
拿iPhoneSE來說,我們都知道iPhoneSE的分辨率為
640 x 1136
,而如果我們使用chrome調試工具将頁面切換為移動端裝置視圖,我們會發現chrome顯示的裝置分辨率為
320 x 568
。
這是因為我們在手機上定義像素如果還按照大屏顯示器那樣去規定像素的話,文字、識圖都會看起來小到無法識别(想象一下你将顯示器縮小為如同手機那樣的大小你還能看清螢幕上的文字嗎),是以我們規定了一個縮放比來優化顯示效果。
iPhoneSE的縮放比為2,那麼我們将它的實體像素統統除以2,得到的結果便是
320 x 568
,即一個實際像素顯示2個實體像素。
3. 計算頁面元素真實的實體像素
那假如我們再頁面上定義了一個200px寬高的div,那麼它在iPhoneSE上顯示的實際大小為多少呢。
- 如果我們不定義viewport,viewport在所有的顯示裝置上的顯示寬度均為980px。那麼在iPhoneSE上,我們看到的定義的200px寬高的元素的實際實體像素寬高為
。640*(200/980)px
- 如果我們定義了viewport的寬度為裝置寬度,那麼在iPhoneSE上,我們看到的定義為200px寬高的元素的實際實體像素寬高為
,即為640*(200/320)px
。CSS像素*DPR
4. 何為縮放比
縮放比即為我們再meta标簽中設定的
initial-scale
。它指的是當我們用移動裝置去檢視頁面時,頁面會被放大的倍數,隻在我們設定viewport寬度後生效。
比如,當我們定義,如下meta标簽,顯示在ipad等移動裝置上頁面會被放大兩倍:
那縮放比具體有什麼卵用呢?
當我們浏覽一個移動端頁面,針對頁面上的一個按鈕,如果不設定縮放,iPhoneSE和iPhone6 Plus會按照同樣的按鈕大小去展示。但這樣的話iPhone6 Plus由于螢幕更大,顯示按鈕就會顯得過小,觀感上很不協調,是以我們這時候就可以将其縮放比設定為
414/320
即為
1.29
,即代表這個按鈕在iPhone6 Plus上會按照1.29倍等比例放大,這樣整個頁面的觀感就會更好。
當然如果我們采用
rem
機制去動态改變元素的寬高和字型大小,也能達到同樣的效果。