深入理解viewport

這篇文章我已寫成pdf,建議直接下載瀏覽。

鏈接:https://pan.baidu.com/s/1c4cwd7E 密碼:jty1

《對viewport標籤的理解》

——版權所有 @RYZZ

https://www.cnblogs.com/ryzz/

如轉載或引用請加上該鏈接!

前言:(必讀)

前端的小朋友們多多少少接觸過這個標籤,網上有很多關於這個標籤的解釋,但是無疑千篇一律,你不禁都會懷疑他們是不是相互抄襲的。

這篇文章是我自己對這個標籤以及瀏覽器對網頁渲染機制的一個理解(可能有誤,但至少根據這樣的理解能夠說通該標籤各種情況的原因)。

推薦使用Chrome開發者工具的移動端模擬器來測試該標籤,這樣編輯預覽都很方便,當然我這篇文章的測試都是經過安卓(華爲P10)和iOS(iPhone7)測試過的。

文章提出了一些自定義概念(雙下劃線表示),如果在學習中自己總結某個概念有助於你學習,是很好的習慣。

如果你對這篇文章有錯誤之處,懇請指正,但不要帶上髒話,謝謝。

 

目錄:

 

一、標籤用法及其屬性 P2 )

二、幾個專業術語 ( P3 )

三、PC上vp機制和網頁渲染原理 ( P4 )

四、移動端上vp機制和網頁渲染原理 ( P6 )

 

 

標籤一般用法:(不需要過多參數,我覺得用戶還是需要自己的操作空間,當然如果你是想用HTML5開發混合應用,建議加上最大、小縮放和禁止用戶縮放)

<meta name=」viewport」 content=」width=device-width」>

屬性:(屬性各自作用不說了,百度一堆)

width:a value(px) | device-width

initial-scale 範圍是(0.0, 10.0]

minimum-scale 同上

maximum-scale 同上

user-scalable 「yes」 | 「no」

 

來認識幾個與屏幕(包括手機屏幕,電腦屏幕,平板屏幕等等)有關的術語:

(1) 尺寸(單位:inch,即英寸):就是我們俗話說的你的手機是幾寸的,它的大小是你手機對角線的長度。

(2) 分辨率(單位:px,即像素):指你手機的寬 × 高,比如iPhone7的分辨率就是750 × 1334px

(3) 像素密度(單位:dpi(dot per inch)或ppi(pixel per inch),安卓習慣用前者而蘋果習慣用後者):對角線的像素個數除以對角線長,比如iPhone7的ppi = √(7502 13342) / 4.7 ≈327

(4) 設備像素(單位:px):指的是組成屏幕的最小的單位,比如iPhone7水平就有750個設備像素,有時也稱爲像素點或點。

(5) 設備獨立像素(單位:dp):簡稱dipdevice independence pixel),是一種虛擬像素,CSS中的px單位就是一種設備獨立像素,它能保證使用同一種設備獨立像素單位的相同值在不同設備上顯示的大小差不多。(如果我沒講清楚的話,這個你可以百度瞭解一下)

(6) 設備像素比(無單位,是個比值):簡稱dprdevice pixel ratio),指該設備上一個設備獨立像素等於多少設備像素,比如CSSiPhone7中,1px(這個px是設備獨立像素的一種單位) =  2px(這個px是設備像素,就是iPhone7上的像素點)。使用window.devicePixelRatio屬性來獲取CSS的一個px(設備獨立像素)在該設備上等於多少個px(設備像素),即設備像素比。

(7) viewport:簡稱vp,我們不做中文翻譯,下面用圖片來說明。(因爲我覺得做了翻譯反而會依據表面意思被誤導,如果你有強迫症,我建議你翻譯成「網頁渲染圖層」)

 

 

我們現在來了解一下PC上瀏覽器渲染網頁的原理,這會有助於我們瞭解什麼是vp以及移動端的佈局原理。

看下圖:(畫的有點抽象,儘量去理解)

 

圖中有個瀏覽器(有URL地址欄和三個黑色橢圓的那個大矩形就是),瀏覽器中淡藍色部分就是我們瀏覽器顯示網頁的那個窗口(即window,html和window是重合的,但是body有8px的margin),而淡綠色的就是vp。這幅圖顯示的是網頁過寬時候,我們拖動水平滾動條的滑塊看頁面時候的情況(淡藍色底下有個黑色的實心矩形,就是滑塊)。

 

如果你對window, html, body之間的默認佈局不瞭解的話,建議先看下下圖:

說明了:html(黑色線框)默認和window是重合的(去掉邊框的話),body其實可以看做一個div元素,那麼body也應該是獨佔一行(塊級元素的霸氣所在),所以紅色線框的body也是獨佔一行的(注意body自帶margin:8px,所以它與html有邊距),然後再是綠色線框的div,同樣獨佔一行。

 

 

vp在PC瀏覽器上工作原理的歸納:

PC上,vp默認和window(即瀏覽器窗口,它等價瀏覽器可顯示網頁的區域」以及「瀏覽器可見區域」,這四個名詞都是同個概念!)重合,也就是說vp的默認寬高就是window的寬高。

再來說個概念,網頁內容最小寬:網頁能夠正常呈現的最小寬度

<style>

div{float:left}

.a{width:220px;height:100px;background:yellow}

.b{width:10%;height:100px;background:red}

</style>

<body>

<div class=」a」></div><div class=」b」</div>

</body>

如果瀏覽器窗口最大寬度爲1000px(當前瀏覽器窗口的寬度,可以通過window.innerWidth獲得),那麼這個網頁的最小寬就是220px 1000px * 0.1 = 320px。

 

如果一個網頁內容最小寬等於或小於body的width時,我們稱這種佈局爲合理佈局如果body裏面的元素最小寬之和不超過body,那麼我們看網頁就不需要水平移動了,直接從上往下瀏覽即可,瀏覽就很輕鬆很人性化,所以稱之爲合理佈局),否則如果超過body的width(這時稱爲異常佈局),這時vp的寬會被迫放大,直到剛好包裹住網頁的內容的最小寬,然後再放入瀏覽器的window中,所以就會在底部出現水平滾動條。上面說了如果網頁內容最小寬大於body時會有水平滾動條,那麼如果網頁內容的高(一般來說網頁元素的高不會設置百分比)大於vp的高(vp的高默認就是當前window的高,前面說過),那麼就會出現垂直滾動條。(body的高是不會像寬一樣被撐破的)

也就是說,網頁都是渲染到vp上去的,然後把vp放到瀏覽器窗口中給用戶顯示。

 

 

最後我們來說移動端的瀏覽器網頁渲染原理:(以iPhone7爲例)

在不加viewport標籤時,此時iPhone7的vp寬默認980px,高默認1744px。(這個vp的寬比高就是iPhone7手機的分辨率寬比高值,都約等於0.56,有木有發現。但這點要和PC端的vp區別開,PC端的vp的高寬不受比例約束!)這時,會和PC端一樣,在這個980px寬的vp的body(手機上body還是有8px的外邊距)中加入網頁內容,並且一般不超過body(即合理佈局),網頁在vp中渲染好之後,縮小這個vp使得vp的高和手機瀏覽器可見區域高一樣時爲止,所以你一般點開沒有做移動端優化的網站都是一個被縮小過的網頁。但是,如果這個網頁是個異常佈局呢?即網頁內容最小寬超過了body,那麼這個vp會被迫放大(沒錯和PC端一樣)到剛好包裹住網頁內容最小寬,這時vp就大於980px了,那麼手機瀏覽器該如何縮放呢?還是一樣,異常佈局只是影響了vp的寬,沒有影響vp的高,所以還是縮小到vp的高和手機瀏覽器窗口(這裏用了窗口,即window,它也等價於瀏覽器可見區域,不要搞混了,同個東西,上面說過)的高一樣爲止了,這意味着這時手機瀏覽器底部會有一個水平滾動條,就是用來滑動來看超出的那些部分(即異常佈局的超過body的部分)。

很抽象?看下圖:

 

矩形A表示手機瀏覽器窗口,iPhone7的是375px

矩形B表示iPhone7的默認vp

矩形C表示一個異常佈局網頁,它的最小寬大於vp的寬,所以默認的vp寬會被放大至剛好包裹住網頁的最小寬(紅色箭頭所示),但是vp的高不會被相應放大(就變成了紅色線框的矩形大小)。這時,異常佈局的網頁在vp渲染好了,然後要放入窗口裏了,它會被縮小,直到vp的高和窗口的高一樣,這樣就會出現一個問題,異常佈局的網頁超出body(即超出默認vp寬)的內容會顯示在窗口外,所以瀏覽器地不會出現一個滾動條,來看這異常的部分。

 

嘮嘮叨叨那麼多,那麼加上viewport標籤呢?這還簡單了?

如果設置爲width=device-width,意味着把默認vp按比例變成窗口寬的大小。(注意,vp的寬高都是被約束的,縮放寬時高也會被縮放,縮放高時寬也會被縮放,但是上面講到的在異常佈局中除外)這時,vp將與窗口重合。那麼,如果是個合理佈局的網頁,那麼顯示出來的就是一個很標準的移動優化的網頁,反之,如果是個異常佈局,那麼vp是不會再縮小的,因爲vp的高已經和窗口高一樣了,但是vp的寬卻要包裹住異常佈局的網頁的最小寬,所以vp的寬會大於device-width指定的值(在iPhone7上爲375px),所以會加上水平滾動條。同樣,這個異常佈局的網頁的vp的寬高的縮放就不會被比例約束,因爲它的寬是被迫縮放的。

如果設置的width大於device-width,比如設置個500px,那麼vp的寬就是500px,高等比例放大爲585 * (500/375) = 780px。(585px是width=375px時的vp高)這時的網頁渲染原理不就和不加viewport一樣嘛?合理佈局就縮小vp使得vp高等於窗口高;異常佈局會增大vp的寬,但是vp的高不會等比例增大(因爲vp的寬是被迫增大的),然後在縮小vp使得vp高等於窗口高,並且出現水平滾動條。

如果設置的width小於device-width,比如設個200px,那麼vp寬高就是200px × (200 / 375 * 585)px,然後再是看是否是合理佈局,是的話等比例放大使得vp高等於窗口高,不是的話,就增加vp的寬,然後再等比例放大使得vp高等於窗口高,同樣地,會出現水平滾動條。

 

2018年1月31日


更多專業前端知識,請上 【猿2048】www.mk2048.com