viewports剖析

記得要微笑發表於2021-11-18

在這個迷你係列的文章裡,我將解釋viewports和多種重要的HTML標籤元素的寬度是如何工作的,例如<html>標籤。同樣也會解釋windowscreen的寬度問題。

第一部分主要關於桌面(pc)瀏覽器,基本目的在於為移動端(mobile)瀏覽器上,本話題的討論建立舞臺。絕大多數web開發人員已經對pc的概念有了直觀的認識。mobile擁有相同的概念,但是更加複雜。如你所知,一個友好的預熱將極大的幫助你理解mobile瀏覽器。

概念:裝置的pixelsCSSpixels

首先你應當理解CSSpixels,以及它和裝置的pixels的區別。

CSS畫素是一個抽像的單位,主要使用在瀏覽器上,用來精確度量Web頁面上的內容。一般情況之下,CSS畫素稱為與裝置無關的畫素(device-independent pixel),簡稱DIPsCSS畫素可以理解為在樣式檔案中書寫的畫素,在使用者沒有縮放頁面時,CSS畫素等價於裝置獨立畫素。

裝置獨立畫素也稱為密度無關畫素,可以認為是計算機座標系統中的一個點,這個點代表一個可以由程式使用的虛擬畫素(比如說CSS畫素),然後由相關係統轉換為物理畫素。比如 iPhone6375px就是裝置獨立畫素,物理上裝置螢幕的寬度,螢幕尺寸

物理畫素又被稱為裝置畫素,他是顯示裝置中一個最微小的物理部件。每個畫素可以根據作業系統設定自己的顏色和亮度。正是這些裝置畫素的微小距離欺騙了我們肉眼看到的影像效果。我們常說的解析度就是指的物理畫素,比如iPhone6750px就是指物理畫素,物理畫素越高,圖片就越清晰

我們姑且認定裝置的pixels為正確(標準)的pixels寬度。這些pixels決定了你工作所用的那些裝置上正式的解析度。在大多數情況下,能夠從screen.width/height上取出具體值。

如果使用者縮放(zoom)了瀏覽器,當然必須改變計算方式。例如使用者縮放了200%,上訴顯示器只能橫排容納4個上述元素了。

現代瀏覽器上的縮放,是基於“伸展”pixels。結果是,html元素上的寬度並沒有因為縮放200%而由128pix變成256px,而是真實的pixels的被計算成了雙倍。html元素在形式上依然是128CSSpixels,即便它佔用了256裝置的pixels

換言之,縮放200%將一個單位的CSSpixels變成了4倍的裝置的pixels那麼大,即寬度 * 2高度 * 2面積擴大了2 * 2

下列圖片將清楚的解釋這個概念。如圖1-141畫素,縮放為100%html元素,CSSpixels完整的和裝置的pixels重疊

Viewport剖析

當我們縮小瀏覽器時,CSSpixels開始收縮,導致1單位的裝置的pixels上重疊了多個CSSpixels,如圖1-2

Viewport剖析

同理,放大瀏覽器時,相反的事情發生了,CSSpixels開始擴大,導致1單位的CSSpixels上重疊了多個裝置的pixels,如圖1-3

Viewport剖析

總體而言,你只需要關注CSSpixels,這些pixels指定你的樣式被如何渲染。

裝置的pixels幾乎對你毫無用處。但對使用者而言卻不是這樣。使用者會縮放頁面,直到他能舒服的閱讀內容。但是你不需關心這些縮放級別。瀏覽器會自動的保證你的CSSpixels會被伸展還是收縮。

100% 縮放

本例設定縮放級別為100%。現在我們更嚴謹的定義,如下:

在縮放級別為100%時,1單位的CSSpixel是嚴格相等於1單位的裝置pixel

100%縮放的概念非常有利於表述接下來的內容,但你不必在日常工作中過度擔憂這個問題。在桌面系統上,你通常會在100%縮放級別下測試你的網站,但即便使用者縮放,CSSpixels的魔法依然能保證你網站外觀儲存相同的比例。

螢幕尺寸 Screen size

screen.width與screen.height

  • 含義:使用者的螢幕的完整大小。
  • 度量:裝置的pixels
  • 相容性問題:IE8裡,不管使用IE7模式還是IE8模式,都以CSSpixels來度量

我們先了解一些特殊的尺寸:screen.widthscreen.height。這兩個屬性包含了使用者螢幕的完整寬度高度。這些尺寸使用裝置的pixels來定義,他們的值不會因為縮放而改變:他們是顯示器的特徵,而不是瀏覽器。如圖1-4所示。

Viewport剖析

很有趣吧?但是我們拿來何用呢?

簡單的說,木有用!使用者的顯示器寬度對我們而言不重要 – 除非你想要用他們做網路統計資料.

瀏覽器尺寸 Window size

window.innerWidth與window.innerHeight

  • 含義:包含滾動條尺寸的瀏覽器完整尺寸
  • 度量:CSSpixels
  • 相容性問題:IE不支援,Opera用裝置pixels來度量

相反的,你想要知道的瀏覽器的內部尺寸。它定義了當前使用者有多大區域,可供你的CSS佈局佔用。你可以通過window.innerWidthwindow.innerHeight來獲取。如圖1-5

Viewport剖析

顯然,視窗的內部寬度使用CSSpixels,你需要知道多少你自己定義的元素能塞入瀏覽器視窗,而這些數量會隨著使用者放大瀏覽器而減少(瀏覽器放大時,window.innerWidthwindow.innerHeight會變小)(如圖1-6)。所以當使用者放大顯示時,你能獲取的瀏覽器視窗可用空間會減少,window.innerWidthwindow.innerHeight就是縮小的比例。

Opera瀏覽器在這個問題上是一朵奇葩,當使用者放大瀏覽器顯示時不少。所以當使用者放大顯示時,你能獲取的瀏覽器視窗可用空間會減少。window.innerWidthwindow.innerHeight 卻並不會減小。在桌面瀏覽器上,這個特性很煩人,但在移動裝置瀏覽器上簡直是致命的,後面我們會討論

Viewport剖析

注意,視窗內部寬度和高度的尺寸,包含了滾動條的尺寸。(這主要是來至於歷史原因)

滾動移位 Scrolling offset

window.pageXOffsetwindow.pageYOffset

  • 含義:頁面的移位
  • 度量:CSSpixels
  • 相容性問題:pageXOffsetpageYOffsetIE 8 及之前版本的IE不支援, 使用”document.body.scrollLeftanddocument.body.scrollTop” 來取代

window.pageXOffsetwindow.pageYOffset定義了頁面(document)的相對於視窗原點的水平、垂直位移。因此你能夠定位使用者滾動了多少的滾動條距離。如圖1-7

Viewport剖析

該屬性也以CSSpixels來度量,同上面的問題,你想要知道在使用者放大視窗的情況下,使用者向上滾動了多少的滾動條。

原理上來說,在使用者放大瀏覽器時,向上滾動了頁面,window.pageXOffset與window.pageYOffset會改變。但當使用者放大頁面時,瀏覽器會嘗試著儲存使用者當前可見的頁面的元素依然在可見位置。雖然該特性表現得不如預期,但它意味著:在理論上 該情況下 window.pageXOffsetwindow.pageYOffset並沒有改變,被使用者滾出螢幕的CSSpixels幾乎儲存不變。如圖1-8

Viewport剖析

概念:視窗 viewport

在我們繼續討論更多的JavaScript的特性properties之前,先介紹另外一個概念:viewport

viewport的功能在於控制你網站的最高塊狀(block)容器:<html>元素。

聽起來有點玄乎,舉個例子~假設你定義了一個可變尺寸的佈局(liquid layout),且你定義一個側邊欄的寬度為width: 10%。當你改變瀏覽器視窗大小時,該側邊欄會自動擴張和收縮。這是什麼原理呢?

技術上講,原理是側邊欄的寬度為它父元素寬度的10%,我們設它的父元素是

且你未指定寬度。那麼問題就變為了<body>的寬度到底是多少?

通常,一個塊級元素佔有起父元素的100%的寬度(這裡有異常情況,暫時忽略)。所以<body>的寬度就是其父元素<html>的寬度。

那麼<html>元素到底有多寬?因為它的寬度恰好為瀏覽器的寬度。所以你的側邊欄寬度width: 10%會佔用10%的瀏覽器寬度。所以的web開發人員都直觀的知道和使用該特性了。 但是你也許不知道原理。在原理上,<html>的寬度受viewport所限制,<html>元素為viewport寬度的100%。

反過來,viewport是嚴格的等於瀏覽器的視窗:定義就是如此。viewport不是一個HTML的概念,所以你不能通過CSS修改它。它就是為瀏覽器視窗的寬度高度 – 在桌面瀏覽器上如此,移動裝置瀏覽器上有點複雜。

影響 Consequences

縮放事件有一些奇怪的影響,你可以在本站上實驗。頁面滾動到最上面,放大瀏覽器2-3倍,網站的寬度會超過瀏覽器視窗。再將頁面滾動到最右邊,你會發現網站最上面的藍色欄目不再對齊了。如圖2-1

Viewport剖析

這個效果反應了viewport是如何被定義的。我定義了最上面藍色欄目的寬度為width: 100%。什麼的100%?當然是

的寬度,同樣是viewport的寬度,同樣是瀏覽器視窗的寬度。

重點:縮放比例100%的情況下很正常,現在我們放大瀏覽器,viewport變得比網站的總寬度更小。對viewport無影響,但頁面的內容溢位了<html>元素,但它卻有屬性overflow: visible。意味著溢位的部分依然會被顯示。

但藍色欄目卻不會溢位。我定義了它寬度為width: 100%,結果瀏覽器為他賦值寬度為viewport的寬度。瀏覽器不會在乎這個欄目的寬度是不是過窄了。如圖2-2

Viewport剖析

頁面寬度 document width ?

我真正想要知道的是頁面內容的總大小,包括超出瀏覽器視窗的部分。到目前為止,據我所知並沒有辦法找到這個值(當然,除非你計算頁面所有部分的寬度包括所有元素的margin,但是這種計算很容易出錯)。

我開始相信我們需要一個JavaScript特性對(property pair)來標示我所謂的頁面寬度 document width(當然,以CSSpixels來度量)。如圖2-3

Viewport剖析

如果我們真的感覺對這事兒很煩躁:為什麼不在CSS中揭露這些值?我期望定義width: 100%來控制頁面藍色欄目的寬度,它基於頁面的寬度而不是元素的寬度。這似乎很棘手(This is bound to be tricky),如果這成功的被實現我也不會感倒驚訝。

度量viewport Measuring the view port

document.documentElement.clientWidth與document.documentElement.clientHeight

  • 含義:viewport的尺寸
  • 度量:CSSpixels
  • 相容性問題:無

你也許想要知道viewport的尺寸,他們可以通過document.documentElement.clientWidthdocument.documentElement.clientHeight來獲取。如圖2-4

Viewport剖析

如果你熟悉DOM,你會知道document.documentElement實際上就是<html>元素:HTML文件的根元素。然而viewport是比<html>更高階別的元素,打個比喻,它是容納<html>元素的元素。那會和你是否給元素賦值width相關(我不建議這麼做,但是卻是可行的)

在那種情況下document.documentElement.clientWidthdocument.documentElement.clientHeight依然給出了viewport的尺寸,而不是<html>元素。(這是特殊的規則只針對這個特殊的元素針對這個特性對。在其餘任何情況下元素使用實際的寬度)如圖2-5。為<html>元素賦值25%。但`document.documentElement.clientWidthdocument.documentElement.clientHeight的值不變。它雖然貌似從<html>元素取值,但實際描述的確是viewport的尺寸。

Viewport剖析

所以document.documentElement.clientWidthdocument.documentElement.clientHeight只會給出viewport的尺寸,而不管<html>元素尺寸如何改變。

兩個特性對 two property pairs

但是viewport的尺寸不是也通過window.innerWidth/Height來描述的麼?嗯,是,也不是。

這兩個特性對有嚴格的區別,幾乎算是吹毛求疵了

  • window.innerWidth/Height包含滾動條
  • document. documentElement. clientWidth/Height不包含

我們能獲取這兩個特性對是因為他們是瀏覽器大戰的殘留。過去Netscape只支援window.innerWidth/HeightIE 只支援document.documentElement.clientWidth/Height。從那時候開始所有其餘瀏覽器都支援這兩個特性。但IE一直未支援window.innerWidth/Height

在桌面系統中,擁有這兩個特性對只是一點小麻煩,但在移動裝置中卻變成了一種祝福。後面我們會看到 。

度量<html>元素 measuring the <html> element

document.documentElement.offsetWidth/Height

  • 含義:<html>的尺寸
  • 度量:CSSpixels
  • 相容性問題:IE用這個值標示viewport的尺寸而非<html>

如果clientWidth/Height一直用以標示viewport的尺寸,我們該如何去獲取<html>元素的尺寸呢?— document.documentElement.offsetWidth/Height。如圖2-6

Viewport剖析

這個特性對真實的讓你訪問塊級元素<html>元素,如果你為<html>元素賦值了寬度,offsetWidth會真實的反應出來。如圖2-7

Viewport剖析

事件座標 Event coordinates

pageX/Y, clientX/Y, screenX/Y

  • 含義:見下文
  • 度量:見下文
  • 相容性問題:IE不支援pageX/YIE使用CSS pixels來度量screanX/Y
  • 詳細描述:

    • pageX/Y:從<html>原點到事件觸發點的CSSpixels
    • clientX/Y:從viewport原點(瀏覽器視窗)到事件觸發點的CSSpixels
    • screenX/Y:從使用者顯示器視窗原點到事件觸發點的裝置 的 pixels

如圖2-8、2-92-10

Viewport剖析

Viewport剖析

Viewport剖析

9成可能你會用到pageX/Y1成左右會使用clientX/Y,screenX/Y基本沒啥用。

Media查詢 media queries

mediaqueries

  • 含義:見下文
  • 度量:見下文
  • 相容性問題:IE不支援.

最後一點文字關於@mediacss屬性。出發點很簡單:你可以根據頁面的特定寬度來定義特殊的CSS規則。舉個例子。

div.sidebar {
  width: 300px;
}
@media all and (max-width: 400px) {
  // styles assigned when width is smaller than 400px;
  div.sidebar {
    width: 100px;
  }
}

如果寬度大於400px,那麼sidebar寬度為300px。反之,sidebar寬度為100px

有兩個相關的media查詢:width/heightdevice-width/device-height。如圖2-11

  • device-width/height使用screen.width/height來做為的判定值。該值以裝置的pixels來度量
  • width/height使用documentElement.clientWidth/Heightviewport的值。該值以CSSpixels來度量

Viewport剖析

到底該使用那個呢?一個很無腦的結果:widthweb開發中不需要對裝置的寬度感興趣,而width卻使按照瀏覽器視窗的大小計算的

所以在桌面瀏覽器中使用width而忘記device-width。接下來我們會看到在移動裝置中有點凌亂。

總結

在此結束對桌面瀏覽器的特性的簡短討論,第二部分主要涉及移動裝置和其與桌面瀏覽器的重要區別。

接下來是第二部分內容,來源於A tale of two viewports — part two一文。

移動裝置瀏覽器的問題

裝置的寬度是移動裝置瀏覽器和桌面瀏覽器的最大區別。移動裝置的顯示通常比桌面瀏覽器顯示同一網站的內容要少。或者縮放瀏覽器變小導致文字無法閱讀,或者只顯示網站適合裝置大小的部分內容。

移動裝置的螢幕寬度比桌面瀏覽器小,經常最大就400px寬,而且通常會更小。(有些手機號稱大寬度,但他們確是在說謊 – 或起嘛給了我們一些無用的資訊)

一些中間寬度的pad裝置(table device)如iPad或傳說中HPwebOS裝置填補了桌面和移動裝置的缺口,但卻沒有解決根本的問題。網站還是必須在移動裝置上工作,我們不得不讓她們在小螢幕上顯示得表現良好。

問題的風暴中心在於CSS,特別是viewport的尺寸。如果我們只是拷貝桌面的樣式到移動裝置,我們的CSS會醜得崩潰

(假設移動裝置的寬度400px)我們回到width: 10%的側邊欄。如果在移動裝置上同理處理,會顯示出40px寬,實在太窄了。你的可變佈局看起來被可怕的壓扁了。

其中一個解決方式是為移動裝置重新建設一個特殊的網站。即使跳開這些基本的問題:你到底該怎麼處理,現實的問題是隻有很少的站長準備好了加入迎合移動裝置而做的改變。

移動裝置瀏覽器供應商期望他們的客戶端提供最好的可能性體驗,即現在意味著“儘可能的像桌面瀏覽器”。因此許多處理手段是必須的。

兩種viewport

因此viewport太窄,不能很好為你的基本CSS佈局服務了。最顯然的解決方式是讓viewport更寬。因此這個需求分為了2個方面:虛擬的viewport(visual viewport)和佈局的viewport(layout viewport)。

George CumminsStack Overflow上解釋了這個基本概念,猛擊

想象下layout viewport是一張大的不能改變大小和角度的圖片。現在你有個更小的框來觀看這張大圖片,這個框被不透明的材料包圍,因而你只能看到大圖片的一部分。你通過這個框子看到的大圖片的部分被稱為虛擬viewport(visual viewport)。你能拿著這個框站得離大圖片遠點(使用者的縮小頁面功能),以一次性看到這個大圖片。或者你能站得近點(使用者的放大頁面功能)以看到一部分。你能改變這個框子的方向,但這張大圖片的大小和形狀都不會改變。

你可以參見解釋詳情by Chris。

visual viewport是當前顯示在螢幕上的部分頁面。使用者會滾動頁面來改變可見部分,或者縮放瀏覽器來改變visual viewport的尺寸。見圖1-1.

Viewport剖析

但是CSS 佈局,特別是感性的寬度(percentual widths)通常是按照layout viewport來定義,而比visualviewport寬很多。

然而<html>元素的寬度繼承於layout viewport,你的CSS應預先準備著需要處理的螢幕(layout viewport)是不是遠遠超過手機螢幕寬度。這用以保證你的網站外觀特性而恰如在桌面瀏覽器上一樣。

layout viewport到底有多寬?每個瀏覽器都不同。iPhone上的Safari使用980pxOpera 850px,安卓的Webkit核心800pxIE 974px

一些瀏覽器有特別的特性:

  • 塞班webkit試著儲存layout viewportvisual viewport同樣寬度。因此,定義百分比寬度的元素會變得巨難看。當然,如果頁面有特定的寬度而不是適合visual viewport的寬度,那麼該寬度的最大值會被設定為850px
  • 三星的WebKit(bada)上)會設定layout viewport和最寬的元素一樣寬
  • 黑莓上layout viewportvisual viewport100%縮放時一樣寬。

縮放 Zooming

兩種viewports都以CSSpixels來度量。當你通過縮放改變visual viewport時,layout viewport儲存不變。

理解layout viewport

為了理解layout viewport的尺寸,我們先看下頁面完全縮小時發生了什麼。許多移動裝置瀏覽器在初始預設開啟以最小縮放模式開啟網站。(即在手機螢幕上展示完整寬度的頁面)。如圖1-2.

Viewport剖析

重點:瀏覽器已經選擇好他們的layout viewport的尺寸,它完整的覆蓋了最小縮放模式下的移動瀏覽器的螢幕。

這時候layout viewport的寬度高度和最小縮放模式下能在頁面上顯示的內容的寬度高度一致。即便使用者縮放,它依然儲存不變。如圖1-3

Viewport剖析

layout viewport寬度通常儲存不變。如果你旋轉你的手機,visual viewport改變,但瀏覽器會縮放頁面以自適應,以達到layout viewport再次和visual viewport同樣寬。如圖1-4

Viewport剖析

這影響到了layout viewport的高度,它突然變得比豎著模式更小(portrait model肖像模式),但web開發者並不關心高度,只在乎寬度。如圖1-5.

Viewport剖析

度量layout viewport

document.documentElement.clientWidth/Height的尺寸

  • 含義:layout viewport尺寸
  • 度量:CSSpixels
  • 完整支援:Opera, iPhone, Android, Symbian, Bolt, MicroB, Skyfire, Obigo
  • 問題:在Iris上它標示visual vieport

    • 三星的Webkit核心瀏覽器,僅當在頁面上寫入<meta viewport>標籤,才正確表示。否則就代表著
    • FireFox以裝置的pixels來度量
    • IE返回1024px 768px,而準確的尺寸儲存在document.body.clientWidth/Height
    • NetFront僅當100%縮放時候才正確
    • 塞班的Webkit1(在S60v3裝置)不支援這些屬性
  • 不支援:黑莓

很幸運瀏覽器由於瀏覽器大戰而遺留給我們2個特性對來度量這兩種viewport

document.documentElement.clientWidth/Height傳遞layout viewport的尺寸,如圖1-6

Viewport剖析

旋轉只關係到高度,而不是寬度。如圖1-7

Viewport剖析

度量visual viewport

window.innerWidth/Height

  • 含義:visual viewport尺寸
  • 度量:CSSpixels
  • 完整支援:iPhone, Symbian, BlackBerry
  • 問題:

    • FireFoxOpera以裝置的pixels返回該數值
    • Android, Bolt, MicroB, 和 NetFrontCSSpixels返回該數值,且為layout viewport的值
  • 不支援:

    • IE,它使用document.documentElement.offsetWidh/Height來表示
    • 三星的Webkit核心瀏覽器,僅當在頁面上寫入<meta viewport>標籤,才正確表示。否則就代表著<html>的尺寸
  • 混亂:Iris, Skyfire, Obigo返回的值不知所云

我們使用window.innerWidth/Height來度量visualvviewport。顯然,隨著使用者縮放瀏覽器,這值會改變,更多、更少的CSS pixels放進了螢幕。如圖1-8

Viewport剖析

很不幸這是一個待完善的部分,許多瀏覽器依然沒有支援對visual viewport的度量。到現在為止,沒有瀏覽器將該度量儲存在其他地方,我猜測window.innerWidth/Height會成為標準,albeit是最強力的支持者。

螢幕 Screen

screen.width and screen.height

  • 含義:螢幕尺寸
  • 度量:裝置的pixels
  • 完整支援:Opera Mini, Android, Symbian, Iris, Firefox, MicroB, IE, BlackBerry
  • 問題:

    • OperaWindows Mobile下只給出橫向尺寸(landscape size)。在S60上工作正確。
    • 三星的Webkit核心瀏覽器,僅當在頁面上寫入<meta viewport>標籤,才正確表示。否則就代表著<html>的尺寸
    • iPhoneObigo僅給出豎直尺寸(portrait sizes)
    • Android, Bolt, MicroB, 和 NetFrontCSSpixels返回該數值,且為layout viewport的值
  • 不支援:

    • IE,它使用document.documentElement.offsetWidh/Height來表示 - 三星的Webkit核心瀏覽器,僅當在頁面上寫入<meta viewport>標籤,才正確表示。否則就代表著<html>的尺寸
  • 混亂:Iris, Skyfire, Obigo返回的值不知所云

pc瀏覽器一樣,screen.width/height標示了裝置螢幕的尺寸,以裝置的pixels度量。和pc瀏覽器一樣,作為web開發人員你永遠不需要這些資訊。你不關心螢幕的物理寬度,而關心當前有多少CSSpixels能供你使用。

Viewport剖析

縮放等級 Zoom level

無法直接獲取縮放等級,但可以使用screen.width除以window.innerWidth來計算。當然,只有這兩個特性被完美支援時才能使用。

幸運的是,縮放等級並不重要。你只需要知道當前有多少CSSpixels能供你使用。你可以從window.innerWidth獲取這些資訊 – 如果當前瀏覽器支援。

滾動位移 scrolling offset

window.pageX/YOffset

  • 含義:見描述
  • 度量:CSSpixels
  • 完整支援:iPhone, Android, Symbian, Iris, MicroB, Skyfire, Obigo
  • 問題:

    • Opera, Bolt, Firefox, and NetFront 總是返回 0.
    • 三星的Webkit核心瀏覽器,僅當在頁面上寫入標籤,才正確表示。
  • 不支援: IE,它使用document. scrollLeft/Top來表示

你同意需要知道當前visual viewport相對於layout viewport的距離。這就是滾動位移,如同在桌面瀏覽器一樣,使用window.pageX/YOffset儲存。如圖1-9

Viewport剖析

<html>元素

document.documentElement.offsetWidth / Height

  • 含義:html元素的整體尺寸
  • 度量:CSSpixels
  • 完整支援:Opera, iPhone, Android, Symbian, Samsung, Iris, Bolt, Firefox, MicroB, Skyfire, BlackBerry, Obigo
  • 問題:

    • NetFront只在100%縮放時返回正確的值.
    • IE,使用這個特性對來表示visual viewport的尺寸。它使用document.body. clientWidth/Height來表示

和在桌面系統一樣,document.documentElement.offsetWidth/Height給出了元素以CSSpixels度量的尺寸。如圖1-10

Viewport剖析

Media查詢 media queries

Mediaqueries

  • 含義:以CSSpixels度量<html>元素或以裝置 的pixels度量裝置
  • 完整支援:Opera, iPhone, Android, Symbian, Samsung, Iris, Bolt, Firefox, MicroB.
  • 不支援:Skyfire, IE, BlackBerry, NetFront, Obigo
  • 備註: 我只測試了瀏覽器是否從正確的特性對裡提取這些值。而特性對裡的值是否正確並不在這裡進行詳細測試。

media查詢如同桌面系統一樣。width/height使用以CSSpixels度量的layout viewport,device-width/height使用以裝置的pixels度量的裝置螢幕(device screen)。

換句話說,width/height 反映document.documentElement.clientWidth/Height的值, device-width/height 反映screen.width/height. (所有瀏覽器遵循同樣原理,即使取值是錯誤的)。如圖1-11.

Viewport剖析

哪個度量對web開發人員更有用呢?我也不知道。

我起初認為device-width更重要,因為它給予了裝置的資訊,我們也許可以使用。例如,你能根據裝置的寬度改變網站的外觀。但是你同樣可以使用<meta viewport>標籤做到這些。因此使用device-width並不是必須的。

那麼width就更有用了麼?也許是。瀏覽器的製造商認為他們給出了一些對網站有用的寬度的細節。但這些內容卻含糊(混亂),因而width media 查詢並不真正給出其餘資訊。

所以我沒有做決定。現在我認為media查詢在標識網站處於桌面瀏覽器、pad瀏覽器或手機瀏覽器方面很重要,而在區別不同pad和手機裝置方面並不有用。

事件座標 Event coordinates

Eventcoordinates

  • 含義:見下文
  • 度量:見下文
  • 完整支援:Symbian, Iris
  • 問題:

    • Opera 只有pageX/Y,但滾動頁面過遠時這個值會出錯。
    • iPhone, Firefox, 和 BlackBerryclientX/Y pageX/Y相等
    • Android MicroB screenX/YclientX/Y相等,也就是它們以CSSpixels度量螢幕尺寸
    • FireFoxscreenX/Y值不正確
    • IE, BlackBerry, Obigo 不支援 pageX/Y.
    • NetFront 所以三個值都是screenX/Y.
    • Obigo clientX/YscreenX/Y.
    • Samsung WebKit 總是返回pageX/Y.
  • 未測試:Opera Mini,Bolt,Skyfire

事件座標在桌面瀏覽器上多多少少是支援的。不幸的是,移動裝置上在所測試的12個主流瀏覽器中只有Symbian `WebKitIris`完全正確的支援這3個座標特性。其餘瀏覽器多多少少都存在問題。

pageX/Y,該特性依然是基於頁面的CSS pixels度量的值,如圖在桌面瀏覽器一樣,它是三個特性裡面最有用的。如圖1-12

Viewport剖析

clientX/Y是基於visual viewport的,以CSSpixels度量的值. 這樣做比較靠譜,雖然我不是很確信這樣計算的好處。

screenX/Y基於裝置螢幕以裝置的pixels度量的值。顯然,它使用和clientX/Y同樣的參考,而裝置的pixels沒什麼用。所以我們不需要在意screenX/Y,同在桌面瀏覽器一樣,每個bit都是沒用的。如圖1-13.

Viewport剖析

viewportmeta標籤 meta viewport

Meta viewport

  • 含義:設定layout viewport的寬度
  • 度量:CSSpixels
  • 完整支援:Opera Mobile, iPhone, Android, Iris, IE, BlackBerry, Obigo
  • 不支援:Opera Mini, Symbian, Bolt, Firefox, MicroB, NetFront
  • 問題:

    • Skyfire 不能處理我的測試頁面。
    • 在三星的wibkit瀏覽器下,出現會改變一些特性對的值。
    • Opera Mobile, iPhone, Samsung, and BlackBerry 不允許使用者在設定viewport後再進行縮小操作(do not allow the user to zoom out.)

最後我們討論<meta name="viewport" content="width=320">;最初這是Apple的一個html擴充套件標籤,但被許多瀏覽器複用,意義是設定layout viewport的寬度。為了理解它的含義,我們退一步看看基礎。

假設你建立一個頁面,並不為它賦值width。那麼它會伸展開來佔據100%viewlayout的寬度。絕大多數瀏覽器縮小這個頁面以在一屏的寬度上顯示這個layout viewport。我們獲得如下效果。圖2-1.

Viewport剖析

比如,開啟PC端百度頁面,頁面沒有設定Meta viewport,會由於移動裝置的螢幕一般都比PC小很多,webkit瀏覽器會將一個較大的“虛擬”視窗對映到移動裝置的螢幕上,預設的虛擬視窗為980畫素寬(目前大部分網站的標準寬度),然後按一定的比例(3:12:1)進行縮放。也就是說當我們載入一個普通網頁的時候,webkit會先以980畫素的瀏覽器標準載入網頁,然後再縮小,注意這個縮小是一個全域性縮小,也就是頁面上的所有元素都會縮小,縮小這個頁面以在一屏的寬度上顯示

image-20211114195914336.png

使用者會立馬放大頁面,雖然會起到效果,但絕大多數瀏覽器會儲存元素完整的寬度(保持元素定位的不變),而導致閱讀困難(文字超過螢幕),如圖2-2

Viewport剖析

比如,上述例子,頁面在放大後,內容會超過螢幕

image-20211114200109805.png

(唯一不同的是Android下的Webkit核心瀏覽器,他會剪短長串文字的html元素,以讓他們適應螢幕。這簡直太有才了,我覺得其餘所有瀏覽器都應該複用這個特性。我會在再以後全面的寫這方面內容)

現在你可以嘗試著設定htm{width: 320px}。現在<html>元素收縮,隨之所有的會計元素都佔有100%<html>寬度:320px。當使用者放大瀏覽器顯示時這樣做工作得挺好,但在最初載入時的縮小顯示下,使用者感覺很糟糕,因為頁面幾乎沒內容。如圖2-3.

Viewport剖析

為了解決這個問題,Apple引入了meta viewport當你設定<meta name="viewport" content="width=320">,你網站的layout viewport變成了320px。頁面的初始狀態就很正確了。如圖2-4

Viewport剖析

你能任意設定layoutwidth的寬度,甚至包括device-widthdevice-width由以裝置的pixels度量screen.width來設定。

在這裡有個鉤子(There’s a catch here)。有時嚴格的screen.width一點意義都沒有,因為pixels的值太大了。例如,Nexus One上的嚴格寬度是480px,但Google的工程師覺得在使用者設定device-width時,將layout viewport設定為480太大了。他們砍成了2/3,提供320px,和iPhone上一致。

假如,像傳言中,新的iPhone將提供一個巨大的pixel值(並不等於一個巨大的螢幕,只是解析度),如果他們沿用這個特性:device-width320,我一點都不會驚訝。或許最終device-width會直接意味著320px

總結

為什麼要設定layout viewportideal viewport呢?比如iPhone6的理想ideal viewport的寬度是375px
如果不設定meta viewport,預設會以980px或者800pxlayout viewport繪製頁面,然後縮小到一屏顯示,頁面佈局可能會發生錯亂(比如web頁面是在1000px寬度下佈局,現在要在預設的800px下佈局,可能會導致某些元素佈局錯亂)或者頁面元素被縮放得太小,看不清。
如果設定meta viewport,但layout viewport不為裝置獨立畫素,頁面會以設定的layout viewport繪製佈局,不會縮放,正常頁面顯示的寬度可能大於或者小於layout viewport,實際佈局也有可能錯亂。
如果能將layout viewport設定為裝置獨立畫素,然後使用rem或者其他方案做適配(機型太多,需要適配),就能保證同樣的網站在不同解析度的裝置上看起來都是一樣或差不多。

相關研究

許多相關研究將會在以後展開:

  • position: fixed。一個固定位置的元素,如我們所知,定位於viewport。但到底是哪個viewport?我的研究結果如下:猛擊
  • 其餘media 查詢:dpi, orientation, 特別是dpi是個災難性的區域,不僅僅因為所以瀏覽器都返回96dpi(通常這個值是錯誤的),而且因為我們不知道web開發人員到底對哪部分感興趣。一個相關問題
  • 當我們的元素大於layout viewport<html>時會發生什麼?如果我們在layout viewport320px的頁插入了一個1500px元素,如果我們為<html>設定了overflow: visible時,它會超出。是否意味著實際的viewport能比layout viewport更寬?此外,這種情況發生時一箇舊的Android裝置(Nexus One)擴大HTML元素。這是個好主意麼?

相關文章