國內有關viewport的文章和信息,我想大多來源於PPK的文章(篇一,篇二)。從二手資料獲取到的信息老是不夠深, 也有限,我就有不少地方無法理解,看完原文才理解地透徹,推薦你去看看。有時間我想把這兩篇文章翻譯出來,既鍛鍊翻譯能力,又學習技術,一箭雙鵰;如果對你們還有點幫助,那就更好了。css
有些基礎概念,你們看得不少,但未必真理解透了,有必要好好澄清。html
因爲一些術語翻譯成中文,我以爲更容易混淆,因此保留英文名稱,容易辨別和理解。前端
Device Pixel,說出來你們都知道,設備的物理像素。沒錯,它是指設備顯示屏幕的實際像素。設備呈現畫面是靠一些單顏色的色塊顯示的,這個色塊在屏幕上就是一個一個小點,它們排列組合造成顯示畫面,這些在屏幕上實際顯示的點就是設備像素。java
設備的分辨率單位就是device pixel
。好比,設備分辨率是320*480
,表示橫向有320
個點,即320
個device pixel
,縱向有480
個點,即480
個device pixel
。web
注意,320
,不是長度單位,不是它有320那麼寬,而是表示橫向有320個點,至於這點有多大,那不一樣設備就不一樣樣了。因此,640*960
的設備不必定比320*480
的寬,只是代表前者橫向的點多些,密度大些。因此一樣設備寬度,好比4.7英寸,分辨率能夠是640*960
,也能夠是320*480
。前者像素更多,能顯示的圖像信息更多,但咱們看到的圖像的寬度是同樣的,只是前者清晰,後者畫質差些。chrome
CSS Pixel, 你們叫法不同,有設備獨立像素,相對像素,參考像素(reference pixel,這個叫法相對靠譜),懶得翻譯了,就叫CSS像素,形象,由於這個像素就是指CSS中用的像素,適用於開發者的像素單位。之因此稱爲單位,是由於我以爲它是一種單位體制。開發網站時,咱們用的是一套統一的單位,使得頁面上各元素的佈局和相對大小是固定的。編程
好比,我設定body的寬度是800px
,裏面有一個div,設定的寬度是400px
,那麼表現出來的效果就是這個div佔了body的一半。無論你是在電腦上看,在平板上看,仍是在手機上看,它始終都是佔一半,不一樣的是,電腦上看着寬一些(電腦屏幕有二十幾釐米吧)手機上看着窄一些(手機屏幕不到十釐米)。windows
你看,我設定的寬度是800px
,但不一樣設備上的顯示效果同樣,這就像咱們編程寫了一個通用接口,接口的底層我無論,我只要最後通用的效果;又或者像Java的JVM,你寫通用的java代碼,至於運行在windows上仍是Linux上,它們用的什麼命令執行,你無需操心,我只關心在各個設備上的執行結果是否一致。瀏覽器
CSS pixel就像是這個通用接口或者Java代碼,device pixel就是底層接口。因此CSS Pixel是一種與設備無關的開發者像素單位。bash
各自的概念搞清楚了,再來看看二者的關係。
前面打了個比方,說CSS Pixel就像是一個接口,Device Pixel就像是底層,接口表現出效果,而不用管各類各樣的底層。那麼接口和底層的「適配」是怎麼適配的呢?也就是說當要表現出800px
(CSS pixel)的效果時,各設備怎麼計算用多少實際的device pixel來呈現呢?
對於電腦端,很簡單,所見即所得,也就是800px
的CSS pixel顯示出來就是800
個device pixel。
手機端就複雜些,「適配」機制由手機廠家說了算。廠家根據本身的生產工藝,決定說,我這臺4.7英寸的手機,對外顯示的CSS像素是320*480
(CSS pixel),也就是說,無論手機一行有多少個實際像素點,一行都表示320px
(css pixel),這就是device pixel與css的「適配」機制。
呈現的方式就是,
320*480
分辨率的手機,一行表示320px
(css pixel),而手機一行有320
個點(device pixel),所以恰好一個CSS pixel對應一個device pixel來顯示;640*960
分辨率的手機,一行仍是表示320px
(css pixel),而這裏手機的一行有640
個點(device pixel),所以用2個點(device pixel)來顯示1個px(CSS pixel)示;下面的圖例,css寬高都設置爲2px:
PPK定義了三種viewport:Layout viewport, Visual viewport, Ideal viewport,前二者我是認同的,第三種我認爲應該定義爲「廠家定義的對外適配視窗」更好(Adapt viewport),說理想視窗,反而讓你們迷糊,緣由後面解釋。
Layout viewport, 佈局視窗(PS. 翻譯過來總以爲變了味),它是用於承載咱們的html文檔的一個視窗容器,對,當成容器更容易理解。它有固定寬度,若是裏面的html文檔寬度比它的寬度還寬,就會出現橫向滾動條;若是比它還窄,就會出現空白。
Layout viewport的寬高用document.documentElement.clientWidth
和document.documentElement.clientHeight
得到(單位是CSS pixel,與web開發有關的px都是CSS pixel)。
document.documentElement
就是<html>
元素,得到<html>
所在的客戶端的寬度,其實就是外面容器Layout viewport的寬度
對於電腦端,Layout viewport比較好理解,就是咱們看到的瀏覽器的窗口區域。
手機端就複雜了。
因爲手機端屏幕窄,不能像電腦端那樣看到那麼多的東西,但手機廠商也但願能在手機上查看適配於電腦的網頁,但又不能讓瀏覽器的寬度跟手機屏幕同樣寬,由於那樣的話,咱們的網頁寬度超過了窗口寬度,會出現橫向滾動條。好比瀏覽器的寬度設成和手機屏幕(對外適配屏幕寬度)同樣的寬度320px
(css pixel),而電腦網頁的寬度多是1024px(css pixel),顯然須要橫向滾動,用戶須要右划來查看網頁。
可否不出現橫向滾動條,一加載就看到網頁全貌呢?他們想了個辦法,讓手機瀏覽器寬度仍是足夠寬(好比980px
),手機瀏覽器寬度超過手機屏幕寬度,這時拿手機看瀏覽器的網頁,只看到網頁的一小部分(想象管中窺豹),這時候瀏覽器的寬度是超過手機屏幕的。而後把瀏覽器縮放,縮放到和手機屏幕同樣寬,這時候看到的,就是一個縮小版的電腦網頁。
layout viewport在手機端不直觀,經過上面兩張圖可以更好理解layout viewport。
最後,Layout viewport size(css pixel)一旦設置了就是固定的,即容器設定了就不會變化。頁面加載完成後,它不會由於頁面放大和縮小而改變,改變的是咱們看到的內容範圍,也就是後面要說的visual viewport。
注意,這裏說的瀏覽器寬度,是開發者意義上的寬度,不是咱們見到的尺寸的寬度。好比,layout viewport寬度是980px,那麼它無論放在電腦上顯示,仍是縮放在手機屏幕上,表明的都是980px,若是裏面有一個div是490px寬,那麼咱們看到的效果都是佔一半寬度,只不過電腦上的長度很長,手機上的看着很短,但這個div都是490px。
咱們一般設置viewport的<meta>
,設置的就是layout viewport,能夠理解爲它是瀏覽器中物理存在的視窗。
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
複製代碼
Visual viewport, 可視窗口,是可見到的文檔部分的窗口區域。
想象一張桌子上放了一張地圖,你正在用放大鏡看地圖。桌子就是layout viewport,地圖就是html文檔,放大鏡就是Visual viewport。
Visual viwport size(css pixel)就是你放大鏡裏看到的內容區域的大小,它不是固定的。放大鏡裏看到的是一個縣,visual viewport size就是一個縣的面積那麼大;看到的是一個鎮,visual viewport size就是一個鎮的面積那麼大。
你能夠右手持放大鏡,左手移動地圖來查看不一樣部份內容(固然生活中不會這麼作),至關於手機端滑動查看文檔;你能夠把放大鏡放得離地圖近些或者遠些,來看得更清楚或看得更多,至關於手機端的縮放。想象地圖會縮小,縮小到跟你的放大鏡同樣大,你看到的就是整張地圖。
因此,Visual viewport是文檔可見部分的視窗,就像手機後面有一個瀏覽器,裏面裝了文檔,你拿一個矩形方框在看文檔同樣。
Visual viwport的寬高能夠用window.innerWidth
和window.innerHeight
來獲取,不過支持性不是很是全面,未驗證。
前面二者都是真實存在的視窗,第三種是隻有手機端纔有的概念。
電腦端的網頁在手機端查看,效果確定不如意,過小,但願針對手機端的屏幕,有手機端的理想網頁顯示尺寸。這個尺寸不會太寬,寬到電腦瀏覽器那麼寬;不會太窄,窄到變成一條豎條,要恰好能適配手機的寬度。符合這個尺寸的視窗,PPK稱爲理想視窗,這個理想視窗是相對於用電腦瀏覽器寬度的。我倒認爲應該定義爲適配視窗,由於手機廠家爲本身的手機設置了固定的適配尺寸,即,我這臺手機橫向表明多少個CSS pixel, 縱向表明多少個CSS pixel, 這是定死的。
手機分辨率也是固定的。所以device pixel和css pixel的適配關係也就固定了。也就是咱們常見到的DPR
。
且不說是否是理想視窗,看看安卓那一堆的DPR,1.5, 2, 2.5, 3.5, 亂七八糟,適配尺寸五花八門,誰知道它們定出來的適配尺寸是否是理想的。蘋果的尺寸都好歹有規律,DPR成倍數關係,適配尺寸也就那幾種。
所以,Adapt viewport是手機廠商設定的該手機的適配窗口尺寸,即屏幕的橫向縱向表明的CSS pixel數,與手機的分辨率無關。
320*480
, Adapt viewport size能夠是320*480
,橫向320px(CSS pixel),一個CSS pixel對應一個device pixel;640*960
, Adapt viewport size也能夠是320*480
,橫向仍是表明320px(CSS pixel),只不過這時一行裏1個CSS pixel用2個device pixel來呈現。adpat viewport的寬度經過<meta>
標籤裏的device-width獲得,以及媒體查詢的device-width
<!-- 設置layout viewport的寬度爲adapt viewport的寬度(好比320px) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
複製代碼
@media screen and (max-device-width: 375px) {
.footer {
background-color: black;
}
}
複製代碼
注意,width是layout viewport的寬度,device-width纔是adapt viewport的寬度,也就是廠家設定的頁面顯示適配寬度。你們能夠用chrome的手機模式測試下。這也好理解,特別強調device-width,就表示廠家對這臺設備對外宣稱的設備寬度,用來講明它橫向表示多少像素(css pixel),縱向多少寬度(css pixel)。
看看
<meta>
標籤的設置width=device-width
, 就是讓layout viewport的寬與adapt viewport的寬一致,從這裏也能夠區分width, device-width的意義了。
關於width和device-width的區別也能夠參看此文章:Media Queries: Width vs. Device Width
viewport的meta是蘋果手機最開始引入的,用來設置屏幕的佈局尺寸(layout viewport),後來安卓也跟隨其方法,都支持了這個標籤。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minum-scale=1.0, user-scalable=no" />
複製代碼
device-width(css pixel)
, 表示手機的adapt viewport width(css pixel)
,也就是廠家設定的適配尺寸。視窗縮放,這個東西困擾了我好久。
首先思考的是,縮放的是什麼視窗?Layout viewport? visual viewport?
答案是,Layout viewport。
試想以前放大鏡的例子,此次換成用一塊黑色矩形邊框的玻璃看地圖,地圖和玻璃的距離固定,要縮放地圖怎麼辦?玻璃(手機屏幕)大小是固定的,因此要縮放地圖。
玻璃不動,地圖放大,玻璃裏看到的地圖文字就變大了(至關於文檔字體變大),但所看到的地區的面積變少了(原來看到一個縣,如今只能看到一個鎮),看到的面積變小,也就是visual viewport size變小了;地圖縮小,則反之。
補一句,放大時,visual viewport size變小,這裏可能比較費解,以前說visual viewport size是看到的內容區域的大小,咱們能耐看到的文檔內容變少了,於是visual viewport size變小了。
那麼<meta>
標籤中的scale是設置什麼的呢?initial-scale=2的意義是什麼?
始終記得,viewport<meta>
標籤設置的是layout viewport。前面也說了scale是對layout viewport的縮放,因此首先scale是設置layout viewport的。
可是這裏還沒這麼簡單,這個scale還有一層意思,就是將layout viewport縮放後,要使其能剛恰好鋪滿屏幕(fit the screen)。
舉個例子,initial-scale=0.5
,首先它表示將layout viewport縮小到原來的一半;其次,縮小後,整個layout viewport要恰好鋪滿這個屏幕,換句話說,這時候的visual viewport尺寸就恰好等於layout viewport尺寸,由於咱們看到了layout的所有。
如今就至關於作一道小學數學應用題:
===================================
已知
adapt viewport
的尺寸爲375*667(css pixel)
,即layout viewport
不進行縮放,且尺寸也爲375*667時,那麼整個瀏覽器頁面要恰好鋪滿屏幕。問,假設將layout viewport縮放至原來的一半後,其恰好鋪滿整個屏幕,layout viewport尺寸須要多大,此時的visual viewport尺寸是多少?
解:
layout viewport
尺寸爲375*667
時,即scale=1,恰好鋪滿整個屏幕,此時visual viewport
尺寸等於layout viewport
尺寸layout viewport
尺寸爲750*1334
時,假設不對layout viewport
進行縮放(scale=1),此時layout viewport
有一半伸展到了屏幕外面,只有一半顯示在手機中,visual viewport尺寸爲375*667
。- 接上面,此時若是把
layout viewport
縮放到原來的一半,那麼伸展在屏幕外面的區域縮到了手機屏幕中,整個layout viewport恰好鋪滿屏幕,此時visual viewport尺寸爲750*1334
。
答:
layout viewport
尺寸須要750*1334
,此時visual viewport尺寸爲750*1334
。
====================================
從上面的推導能夠看出一個關係:當scale=0.5時,adapt viewport是layout viewport的一半,即
adapt-viewport = 0.5 * layout-viewport = scale * layout-viewport
複製代碼
那麼
layout-viewport = adapt-viewport / scale
複製代碼
因爲scale的定義要求最後縮放的結果是layout viewport的尺寸恰好鋪滿屏幕,鋪滿屏幕就是visual viewport了,所以這種狀況下layout-viewport-size = visual-viewport-size
。因而,
*【visual-viewport = layout-viewport = adapt-viewport / scale】
注意,這裏的layout-viewport與adapt-viewport的關係是基於scale得出的關係,若是layout viewport width另外單獨定義了(如定義width=400),那麼visual viewport不必定等於layout viewport。
這就是定義scale後得出的關係。只要有了scale,就有了layout viewport和visual viewport的尺寸。
scale是經過initial-scale來定義的,它表示頁面第一次加載時的scale,此後若是頁面修改了這個值,再刷新是無效的,須要關閉從新打開頁面。
前面說了設置了scale,就有了layout viewport,若是同時還定義了width呢?
例如:假設設備的adapt viewport爲320*480
。定義meta:
<meta name="viewport" content="width=700, initial-scale=0.5">
複製代碼
width=700
,定義了layout viewport寬爲700;initial-scale=0.5
, 能夠得出layout viewport爲640那麼問題來了,取那個呢?
答案是,取最大的那個值。
visual-viewport-width=640px(css pixel)
, layout-viewport-width=640px(css pixel)
layout-viewport-width=700px(css pixel)
(若是width設置爲600,那麼layout-viewport
寬仍是640px)產生的效果就是屏幕有滾動條,須要滾動一點點(60像素)。
若是不設置viewport <meta>
標籤,那麼layout viewport寬度是多少,visual viewport是多少,scale又是多少?
layout viewport大多數瀏覽器默認是980px,有部分瀏覽器是其餘值。手機瀏覽器廠商爲了提升用戶體驗,默認會縮放layout將整個layout鋪滿屏幕顯示,使得頁面不會出現橫向滾動條。咱們看到所有頁面,因此visual viewport尺寸等於layout viewport,所以visual viewport寬等於980px(css pixel)
。
再根據前面的計算公式visual-viewport = adapt-viewport / scale
, 那麼
scale = adapt-viewport / visual-viewport
複製代碼
假設手機適配尺寸adapt-viewport爲375*667(css pixel)
,那麼
scale = 375/980 = 0.382653
複製代碼
這個值瀏覽器是自動計算得出的。
<meta>
標籤設置的是layout viewport,能夠經過width字段設置,還能夠經過scale字段設置。不設置時,大多數瀏覽器layout viewport爲980px,且徹底鋪滿於屏幕中。囉囉嗦嗦說了這麼多,但願把知道的都表述清楚了。大概我比較笨,看別人的文章,有時以爲不夠詳細,看完不理解,因此我儘可能細緻的把前因後果和注意事項都說了,生怕哪裏掉了什麼。
viewport這塊看了很多文章,寫完這些理解才真正加深了。只要可以理解好viewport的這些知識,移動端的適配就輕鬆多了。