[譯] 關於兩種視口(viewport)的故事:其一

原文地址:http://quirksmode.org/mobile/...css

這篇小短文中,我將會介紹關於viewport與諸如html元素,window 對象,screen 對象這類重要對象在呈現方面的原理。html

本篇討論桌面瀏覽器,其目的是爲了後續討論相似的移動端行爲提供必定基礎。大量web開發者早已憑直覺理解了許多桌面端的概念。可是,在移動端這些概念將變得複雜起來,因此預先對這些咱們熟知的術語進行討論將有助於你對移動端瀏覽器行爲的理解。web

有關概念之:設備像素與CSS像素

你首先須要理解什麼是CSS像素,它與設備像素又有何區別。數據庫

設備像素是咱們直覺上認爲是「正確」的像素。它能給予一個關於你使用何種設備的正式結論,而且能經過'screen.width/height'得到。瀏覽器

假設有一個寬爲128px的元素,屏幕寬度爲1024px。當你最調整合適時,元素會佔屏幕的1/8.ide

若是你縮放屏幕,你將獲得不一樣的結果。假設你將屏幕放大到200%,你的128像素的元素將會佔1024像素的屏幕的1/4。佈局

縮放在現代瀏覽器中的應用無非用像素尺寸的變化來實現。這並非說元素的寬度由128增大到256像素,而是像素點變爲原來的兩倍。形式上,即使元素佔了256的設備像素,它依舊只有128的CSS像素。學習

換言之,一個放大到200%的CSS像素點是設備像素點尺寸的四倍。(寬度兩倍,高度兩倍,整體四倍)。網站

如下圖片將更直觀的描述這一律念。在一個四像素100%縮放的例子中:CSS像素與設備像素徹底重疊。ui

csspixels_100.gif

如今進行縮小操做,CSS像素尺寸開始縮小,這意味着一個設備像素能夠覆蓋多個CSS像素。

csspixels_out.gif

若是你進行放大操做,CSS像素尺寸開始擴大,如今一個CSS像素能夠覆蓋多個設備像素。

csspixels_in.gif

這裏的關鍵點在於CSS像素。它決定了你的樣式表的呈現。

設備像素對於你來講幾乎是徹底無用的。當頁面不方便閱讀時,用戶將經過縮放操做來達到溫馨的閱讀體驗。可是,當縮放的水平沒法達到你的要求時,瀏覽器會自動調整CSS佈局的放大或縮小。

100%縮放

咱們經過假定一個100%縮放的例子展開話題。是時候給一個略微嚴格的定義了:

在縮放水平爲100%時,一個CSS像素實際上等價與一個設備像素。

這個關於100%縮放的概念對於後續的闡釋是很是重要的。但你沒必要太過糾結平常的工做,由於在桌面端你的站點一般都是以100%縮放被打開的,即使用戶使用了縮放,CSS的像素魔法也會確保樣式以相同的比例呈現。

屏幕尺寸

讓咱們來關注一些實際的尺寸,首先先從screen.widthscreen.height提及。即用戶屏幕的高度與寬度。咱們用設備像素來描述這一尺寸,由於其永遠不會變化:注意這是顯示器的特性而非瀏覽器,不要混淆。

desktop_screen.jpg

這看起來至關有趣!但咱們能有這些信息作什麼?

事實上,對於咱們屏幕尺寸並沒什麼卵用。除非你你想要記錄它們並在web統計數據庫中使用,那麼它會有那麼點用。

window 尺寸

相反,你須要知道的是瀏覽器window的內在尺寸。它能反映出用戶能使用多少空間來進行CSS佈局。你能經過window.innerWidthwindow.innerHeight獲取。

圖片描述

能夠明顯看出,window的內部寬度使用CSS像素衡量。你必需要知道你的佈局有多少顯示在瀏覽器窗口中,而且當用戶放大時它們的尺寸時如何減小的。所以,若是用戶進行放大操做時,你在window上的可用空間將會變小而且window.innerWidth/Height也將變小。

(注:這裏雖然進行了放大操做,但因爲只是每一個css像素點變大(設備寬度無變化)且css的尺寸並無改變,因此能呈如今窗口中的尺寸反而時減少的)

(對於Opera存在例外狀況,即當用戶進行放大操做時,其瀏覽器的window.innerWidth/Height並無縮小。這是因爲在Opera 使用設備寬度而非CSS寬度衡量。這在桌面端無關痛癢,但在移動端確實致命的,咱們將在稍後進行討論。)

desktop_inner_zoomed.jpg

滾動偏移(offset)

window.pageXOffset與window.pageYOffset用來衡量文檔中垂直與水平方向上的偏移量。所以,經過這它們你能夠獲取用戶頁面的此刻的滾動狀況。

desktop_page.jpg

它們也是經過CSS像素衡量的。不管是否處於放大狀態,你均可以經過其來獲取文檔被向上滾動的狀況信息。

理論上講,若是用戶向上滾動頁面而且進行放大操做,window.pageX/YOffset將會變化。但瀏覽器默認會保持頁面先後一致,即在用戶放大時保證同一元素出如今頁面頂部可見區域。雖然,這並不老是奏效,但這意味着實踐中window.pageX/YOffset並不真的須要變化。

desktop_page_zoomed.jpg

視口(viewport)的概念

在咱們繼續討論更多JS屬性前,讓咱們先學習另外一個概念視口(viewport)。

視口(viewport)的做用是限制<html>元素,<html>元素是全部網頁塊元素中最高一級的元素。

這可能聽着有點暈,因此舉一個實際的例子。假設在一個流式佈局中,你其中一個邊欄的寬度是10%。如今當你改變瀏覽器寬度時,邊欄會一致的縮放。那麼問題來了,他到底是如何工做?

原理上說,當你給sidebar一個10%的寬度,實際上它得到了父級寬度的10%。讓咱們來考察一下(你並無設定寬度的)body元素。那麼問題來了,body元素的寬度是多少?

一般,全部塊級元素的寬度都會等於父元素(這裏有些特例,但不要在乎細節)。因此<body>元素與其父級<html>元素等寬 element。

那麼<html>元素的寬度又如何?爲什麼他與瀏覽器窗口等寬?因爲與瀏覽器窗口等寬,這也就是爲何你設置邊欄寬度爲10%他就佔據了整個瀏覽器寬度的10%。這是一條全部的web開發人員感性上承認並使用的原理。

你不知道的只是在理論上,這條原理如何實現。理論上,<html>元素的寬度被視口限制。而<html>元素佔據了100%的視口寬度的。

視口寬度又正好等於瀏覽器寬度:就是這麼定義的。視口並不是一個HTML結構,其不受CSS控制。在桌面端,其與瀏覽器窗口長寬一致。但在移動端狀況略微複雜。

結論

在這種狀況下會有許多有趣的現象,用這個頁面你能夠觀察到其中的一個現象。滾動到頂部,放大一到兩次,這樣內容區域就溢出窗口了。

如今當你向右滾動時,會發現頂部藍色區塊並非充分填充的。

desktop_htmlbehaviour.jpg

正是由於咱們將視口定義成如此,才形成了這種現象。咱們定義了藍色區塊的寬度爲100%。那到底是什麼的100%?是<html>元素的100%,<html>元素是和視口等寬的,也是和瀏覽器窗口等寬的。

重點是:上訴結論是在100%縮放的條件下成立的。如今在放大的狀況下,視口寬度將會小於網站的寬度。這對於元素自身影響不大,但對於元素的內容則會溢出<html>元素,而且元素具備overflow: visible屬性,這意味着溢出的內容在任何狀況下都會被顯示。

不過藍色區塊並無溢出。已經將其寬度設爲100%,畢竟,瀏覽器要遵照視口的寬度設定,而非關心當下寬度是否過於狹小。

desktop_100percent.jpg

文檔寬度?

咱們真正須要只曉得是頁面內容區域的真實寬度(包括延伸的部分)。但據我所知不可能得出這個值(固然若是你能計算出頁面中全部元素獨自的狂高,但請你牢記,這極容易出錯)。

我開始相信我門須要一組JS屬性對來獲取被咱們稱之爲「文檔寬度」的值。(固然是以CSS像素爲單位)

desktop_documentwidth.jpg

若是我門真的自我感受時尚,何不將該值引入CSS?我更願意讓藍色區塊基於文檔寬度的100%,而不是<html>元素。(這確是一個難題,即使,若是不能實現我也不會感到驚訝)

瀏覽器廠商們,大家怎麼認爲的?

度量視口

你也許會想獲取視口的值,能夠經過document.documentElement.clientWidth-Height得到。

desktop_client.jpg

若是你熟悉DOM,你就會知道document.documentElement其實是<html>元素(HTML文檔的根元素)。然而,能夠這麼說視口比它(<html>元素)要高一級,它包含了<html>元素。若是你給<html>元素設置了寬度,這會生效。(雖然這可行,但我並不推薦)

在此狀況下document.documentElement.clientWidth-Height仍舊給出視口尺寸而非<html>元素尺寸。(這是一個奇特的規則只有在documentElement元素的這個屬性對才起做用,在其餘例子中使用的仍是實際寬度。)

desktop_client_smallpage.jpg

因而document.documentElement.clientWidth-Height老是給出視口尺寸不論<html>元素的寬度如何。

兩對屬性對

另外,視口的尺寸也能由window.innerWidth/Height獲取?這樣的說法也對也不對。

這二者的正是區別就在於:document.documentElement.clientWidth-Height不把滾動條計算在內,而window.innerWidth/Height則將滾動條計算在內。這算是一些細枝末節的概念了。

實際上這二者是瀏覽器爭霸時代的產物。當時,Netscape 只支持window.innerWidth/Height而IE系列只支持document.documentElement.clientWidthHeight。從那時起,全部其餘瀏覽器開始支持document.documentElement.clientWidthHeight,但IE依舊不支持window.innerWidth/Height

在桌面端上擁有兩個屬性對是有一些累贅,可是咱們即將看到的,在移動端這是多麼大的福音。

度量<html>元素

咱們已經知道,經過clientWidth/Height能夠在任意狀況下獲取視口尺寸。那麼如何獲取<html>元素尺寸?經過document.documentElement.offsetWidthHeight

desktop_offset.jpg

該屬性爲你提供一個方法去獲取塊級<html>元素的寬高。若是你設置了一個寬度,offsetWidth將會從新計算。

事件座標

下面讓咱們談談事件座標。當一個鼠標事件產生,有很多於五種屬性能夠爲你提供關於事件確切位置的信息,在咱們的討論中,如下三種是比較重要的:

  1. pageX/Y 提供以CSS像素度量的相對於<html>元素的位置信息
    desktop_pageXY.jpg

  2. clientX/Y 提供以CSS像素度量的相對於視口的位置信息
    desktop_clientXY.jpg

  3. screenX/Y 提供以CSS像素度量的相對於屏幕的位置信息
    desktop_screenXY.jpg

90%的情形你在使用pageX/Y,你一般發生在你想要知道發生事件的地點相對文檔的位置。而另外10%的情形,你會用到clientX/Y。你基本不會須要處理事件想對於瀏覽器位置的情形。

媒體查詢

最後來談談媒體查詢吧。這是一個很是簡單的概念:由你定義一個特殊的CSS規則,僅在頁面大於,等於,或小於某一特定的值時生效。例如:

div.sidebar {
    width: 300px;
}

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

}

目前,sidebar的寬度時300px,但當寬度低於400px,sidebar的寬度將變爲100px。

那麼問題來了:我門以哪一個寬度做爲基準?

存在兩個相關的媒體查詢:width/heightdevice-width/device-height

width/height使用與documentElement.clientWidth/Height相同的值 (即視口的寬度)。使用CSS像素寬度。
device-width/device-height使用與screen.width/height相同的值 (即設備的寬度)。使用設備像素寬度。

desktop_mediaqueries.jpg

那我門應該使用哪個?那還用問,固然是width。web開發者歷來對設備寬度不來電,他們衷情於瀏覽器寬度。

所以,在桌面端忘記device-width/device-height擁抱width/height吧。我門將會看到在移動端狀況變的複雜起來。

結論

本文是對桌面端瀏覽器行爲的初步探索。

注:翻完發現已經有翻譯版了,質量也不錯,連接給上

相關文章
相關標籤/搜索