與Viewport有關的理解

前言

國內有關viewport的文章和信息,我想大多來源於PPK的文章(篇一篇二)。從二手資料獲取到的信息老是不夠深, 也有限,我就有不少地方無法理解,看完原文才理解地透徹,推薦你去看看。有時間我想把這兩篇文章翻譯出來,既鍛鍊翻譯能力,又學習技術,一箭雙鵰;如果對你們還有點幫助,那就更好了。css

一些重要基礎知識

有些基礎概念,你們看得不少,但未必真理解透了,有必要好好澄清。html

因爲一些術語翻譯成中文,我以爲更容易混淆,因此保留英文名稱,容易辨別和理解。前端

Device Pixel, CSS Pixel

Device Pixel

Device Pixel,說出來你們都知道,設備的物理像素。沒錯,它是指設備顯示屏幕的實際像素。設備呈現畫面是靠一些單顏色的色塊顯示的,這個色塊在屏幕上就是一個一個小點,它們排列組合造成顯示畫面,這些在屏幕上實際顯示的點就是設備像素。java

設備的分辨率單位就是device pixel。好比,設備分辨率是320*480,表示橫向有320個點,即320device pixel,縱向有480個點,即480device pixelweb

注意,320,不是長度單位,不是它有320那麼寬,而是表示橫向有320個點,至於這點有多大,那不一樣設備就不一樣樣了。因此,640*960的設備不必定比320*480的寬,只是代表前者橫向的點多些,密度大些。因此一樣設備寬度,好比4.7英寸,分辨率能夠是640*960,也能夠是320*480。前者像素更多,能顯示的圖像信息更多,但咱們看到的圖像的寬度是同樣的,只是前者清晰,後者畫質差些。chrome

CSS Pixel

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:

  • 左圖是1個css pixel對應1個device pixel,那麼2px(css pixcel)的寬高,用2個device pixel顯示;
  • 右圖是1個css pixel對應2個device pixel,那麼2px(css pixcel)的寬高,用4個device pixel顯示。

Viewport

PPK定義了三種viewport:Layout viewport, Visual viewport, Ideal viewport,前二者我是認同的,第三種我認爲應該定義爲「廠家定義的對外適配視窗」更好(Adapt viewport),說理想視窗,反而讓你們迷糊,緣由後面解釋。

Layout viewport

Layout viewport, 佈局視窗(PS. 翻譯過來總以爲變了味),它是用於承載咱們的html文檔的一個視窗容器,對,當成容器更容易理解。它有固定寬度,若是裏面的html文檔寬度比它的寬度還寬,就會出現橫向滾動條;若是比它還窄,就會出現空白。

Layout viewport的寬高用document.documentElement.clientWidthdocument.documentElement.clientHeight得到(單位是CSS pixel,與web開發有關的px都是CSS pixel)。

document.documentElement就是<html>元素,得到<html>所在的客戶端的寬度,其實就是外面容器Layout viewport的寬度

對於電腦端,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

咱們一般設置viewport的<meta>,設置的就是layout viewport,能夠理解爲它是瀏覽器中物理存在的視窗。

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
複製代碼

Visual viewport

Visual viewport, 可視窗口,是可見到的文檔部分的窗口區域。

想象一張桌子上放了一張地圖,你正在用放大鏡看地圖。桌子就是layout viewport,地圖就是html文檔,放大鏡就是Visual viewport。

Visual viwport size(css pixel)就是你放大鏡裏看到的內容區域的大小,它不是固定的。放大鏡裏看到的是一個縣,visual viewport size就是一個縣的面積那麼大;看到的是一個鎮,visual viewport size就是一個鎮的面積那麼大。

你能夠右手持放大鏡,左手移動地圖來查看不一樣部份內容(固然生活中不會這麼作),至關於手機端滑動查看文檔;你能夠把放大鏡放得離地圖近些或者遠些,來看得更清楚或看得更多,至關於手機端的縮放。想象地圖會縮小,縮小到跟你的放大鏡同樣大,你看到的就是整張地圖。

因此,Visual viewport是文檔可見部分的視窗,就像手機後面有一個瀏覽器,裏面裝了文檔,你拿一個矩形方框在看文檔同樣。

Visual viwport的寬高能夠用window.innerWidthwindow.innerHeight來獲取,不過支持性不是很是全面,未驗證。

Adapt viewport(Ideal viewport)

前面二者都是真實存在的視窗,第三種是隻有手機端纔有的概念。

電腦端的網頁在手機端查看,效果確定不如意,過小,但願針對手機端的屏幕,有手機端的理想網頁顯示尺寸。這個尺寸不會太寬,寬到電腦瀏覽器那麼寬;不會太窄,窄到變成一條豎條,要恰好能適配手機的寬度。符合這個尺寸的視窗,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來呈現。

Adapt viewport獲取

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>

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" />
複製代碼
  • name, meta字段名稱,爲「viewport」
  • content,具體舌質紅字段,用key value鍵值對來表示,鍵值對之間用逗號分隔。
    • width, 直接設置layout viewport寬度,能夠是具體數值,如300,也能夠是一個特殊值device-width(css pixel), 表示手機的adapt viewport width(css pixel),也就是廠家設定的適配尺寸。
    • initial-scale, 初始的縮放值,能夠決定layout viewport尺寸和visual viewport尺寸
    • maximum-scale, 用戶能縮放的最大值
    • minimum-scale, 用戶能縮放的最小值。若是maximum-scal和minimum-scale都爲1,用戶就不能對頁面進行縮放。
    • user-scalable, 用戶是否能縮放,值:yes/no,這個值沒測試,彷佛是爲了兼容性。

viewport scale

視窗縮放,這個東西困擾了我好久。

首先思考的是,縮放的是什麼視窗?Layout viewport? visual viewport?

答案是,Layout viewport

試想以前放大鏡的例子,此次換成用一塊黑色矩形邊框的玻璃看地圖,地圖和玻璃的距離固定,要縮放地圖怎麼辦?玻璃(手機屏幕)大小是固定的,因此要縮放地圖。

玻璃不動,地圖放大,玻璃裏看到的地圖文字就變大了(至關於文檔字體變大),但所看到的地區的面積變少了(原來看到一個縣,如今只能看到一個鎮),看到的面積變小,也就是visual viewport size變小了;地圖縮小,則反之。

補一句,放大時,visual viewport size變小,這裏可能比較費解,以前說visual viewport size是看到的內容區域的大小,咱們能耐看到的文檔內容變少了,於是visual viewport size變小了。

<meta>標籤中的scale

那麼<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的尺寸。

initial-scale

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

那麼問題來了,取那個呢?

答案是,取最大的那個值

  • 根據initial-scale的設置,此時頁面處於縮小0.5倍的狀態,visual-viewport-width=640px(css pixel), layout-viewport-width=640px(css pixel)
  • 因爲設置了width=700,大於640, 故 layout-viewport-width=700px(css pixel)(若是width設置爲600,那麼layout-viewport寬仍是640px)

產生的效果就是屏幕有滾動條,須要滾動一點點(60像素)。

<meta>默認值

若是不設置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
複製代碼

這個值瀏覽器是自動計算得出的。

width, initial-scale只設置一個值

  • 若是隻設置了initial-scale,根據scale的做用,瀏覽器會計算laytou viewport寬度,而且將layout viewport自動適配到屏幕,使其恰好鋪滿屏幕;
  • 若是隻設置了width,那麼瀏覽器也會將layout viewport自動適配到屏幕,使其恰好鋪滿屏幕。scale的值會自動計算。

總結

  1. Device pixel是設備物理像素。CSS pixel是參考像素,與實際像素無關。
  2. Viewport有三種:Layout viewport, Visual viewport, Adapt viewport,Layout viewport是文檔容器視窗,Visual viewport是文檔可見部分視窗,Adapt viewport是手機適配視窗,是廠家爲本身的手機設定的屏幕顯示尺寸。
  3. <meta>標籤設置的是layout viewport,能夠經過width字段設置,還能夠經過scale字段設置。不設置時,大多數瀏覽器layout viewport爲980px,且徹底鋪滿於屏幕中。

最後

囉囉嗦嗦說了這麼多,但願把知道的都表述清楚了。大概我比較笨,看別人的文章,有時以爲不夠詳細,看完不理解,因此我儘可能細緻的把前因後果和注意事項都說了,生怕哪裏掉了什麼。

viewport這塊看了很多文章,寫完這些理解才真正加深了。只要可以理解好viewport的這些知識,移動端的適配就輕鬆多了。

參考文章

相關文章
相關標籤/搜索