在這個迷你係列的文章裡,我將解釋viewports
和多種重要的HTML
標籤元素的寬度是如何工作的,例如<html>
標籤。同樣也會解釋window
和screen
的寬度問題。
第一部分主要關於桌面(pc
)瀏覽器,基本目的在於為移動端(mobile
)瀏覽器上,本話題的討論建立舞臺。絕大多數web
開發人員已經對pc
的概念有了直觀的認識。mobile
擁有相同的概念,但是更加複雜。如你所知,一個友好的預熱將極大的幫助你理解mobile
瀏覽器。
概念:裝置的pixels
和CSS
的pixels
首先你應當理解CSS
的pixels
,以及它和裝置的pixels
的區別。
CSS
畫素是一個抽像的單位,主要使用在瀏覽器上,用來精確度量Web
頁面上的內容。一般情況之下,CSS
畫素稱為與裝置無關的畫素(device-independent pixel
),簡稱DIPs
。CSS
畫素可以理解為在樣式檔案中書寫的畫素,在使用者沒有縮放頁面時,CSS
畫素等價於裝置獨立畫素。裝置獨立畫素也稱為密度無關畫素,可以認為是計算機座標系統中的一個點,這個點代表一個可以由程式使用的虛擬畫素(比如說
CSS
畫素),然後由相關係統轉換為物理畫素。比如iPhone6
的375px
就是裝置獨立畫素,物理上裝置螢幕的寬度,螢幕尺寸物理畫素又被稱為裝置畫素,他是顯示裝置中一個最微小的物理部件。每個畫素可以根據作業系統設定自己的顏色和亮度。正是這些裝置畫素的微小距離欺騙了我們肉眼看到的影像效果。我們常說的解析度就是指的物理畫素,比如
iPhone6
的750px
就是指物理畫素,物理畫素越高,圖片就越清晰
我們姑且認定裝置的pixels
為正確(標準)的pixels
寬度。這些pixels
決定了你工作所用的那些裝置上正式的解析度。在大多數情況下,能夠從screen.width/height
上取出具體值。
如果使用者縮放(zoom
)了瀏覽器,當然必須改變計算方式。例如使用者縮放了200%
,上訴顯示器只能橫排容納4
個上述元素了。
現代瀏覽器上的縮放,是基於“伸展”pixels
。結果是,html
元素上的寬度並沒有因為縮放200%
而由128pix
變成256px
,而是真實的pixels
的被計算成了雙倍。html
元素在形式上依然是128CSS
的pixels
,即便它佔用了256
裝置的pixels
。
換言之,縮放200%
將一個單位的CSS
的pixels
變成了4
倍的裝置的pixels
那麼大,即寬度 * 2
、高度 * 2
,面積擴大了2 * 2
。
下列圖片將清楚的解釋這個概念。如圖1-1
有4
個1
畫素,縮放為100%
的html
元素,CSS
的pixels
完整的和裝置的pixels
重疊
當我們縮小瀏覽器時,CSS
的pixels
開始收縮,導致1
單位的裝置的pixels
上重疊了多個CSS
的pixels
,如圖1-2
同理,放大瀏覽器時,相反的事情發生了,CSS
的pixels
開始擴大,導致1單位的CSS
的pixels
上重疊了多個裝置的pixels
,如圖1-3
總體而言,你只需要關注CSS
的pixels
,這些pixels
指定你的樣式被如何渲染。
裝置的pixels
幾乎對你毫無用處。但對使用者而言卻不是這樣。使用者會縮放頁面,直到他能舒服的閱讀內容。但是你不需關心這些縮放級別。瀏覽器會自動的保證你的CSS
的pixels
會被伸展還是收縮。
100%
縮放
本例設定縮放級別為100%
。現在我們更嚴謹的定義,如下:
在縮放級別為100%
時,1
單位的CSS
的pixel
是嚴格相等於1
單位的裝置pixel
100%
縮放的概念非常有利於表述接下來的內容,但你不必在日常工作中過度擔憂這個問題。在桌面系統上,你通常會在100%
縮放級別下測試你的網站,但即便使用者縮放,CSS
的pixels
的魔法依然能保證你網站外觀儲存相同的比例。
螢幕尺寸 Screen size
screen.width與screen.height
- 含義:使用者的螢幕的完整大小。
- 度量:裝置的
pixels
。 - 相容性問題:
IE8
裡,不管使用IE7
模式還是IE8
模式,都以CSS
的pixels
來度量
我們先了解一些特殊的尺寸:screen.width
和 screen.height
。這兩個屬性包含了使用者螢幕的完整寬度高度。這些尺寸使用裝置的pixels
來定義,他們的值不會因為縮放而改變:他們是顯示器的特徵,而不是瀏覽器。如圖1-4
所示。
很有趣吧?但是我們拿來何用呢?
簡單的說,木有用!使用者的顯示器寬度對我們而言不重要 – 除非你想要用他們做網路統計資料.
瀏覽器尺寸 Window size
window.innerWidth與window.innerHeight
- 含義:包含滾動條尺寸的瀏覽器完整尺寸
- 度量:
CSS
的pixels
- 相容性問題:
IE
不支援,Opera
用裝置pixels
來度量
相反的,你想要知道的瀏覽器的內部尺寸。它定義了當前使用者有多大區域,可供你的CSS
佈局佔用。你可以通過window.innerWidth
和 window.innerHeight
來獲取。如圖1-5
顯然,視窗的內部寬度使用CSS
的pixels
,你需要知道多少你自己定義的元素能塞入瀏覽器視窗,而這些數量會隨著使用者放大瀏覽器而減少(瀏覽器放大時,window.innerWidth
與window.innerHeight
會變小)(如圖1-6)。所以當使用者放大顯示時,你能獲取的瀏覽器視窗可用空間會減少,window.innerWidth
與window.innerHeight
就是縮小的比例。
Opera
瀏覽器在這個問題上是一朵奇葩,當使用者放大瀏覽器顯示時不少。所以當使用者放大顯示時,你能獲取的瀏覽器視窗可用空間會減少。window.innerWidth
與window.innerHeight
卻並不會減小。在桌面瀏覽器上,這個特性很煩人,但在移動裝置瀏覽器上簡直是致命的,後面我們會討論
注意,視窗內部寬度和高度的尺寸,包含了滾動條的尺寸。(這主要是來至於歷史原因)
滾動移位 Scrolling offset
window.pageXOffset
與window.pageYOffset
- 含義:頁面的移位
- 度量:
CSS
的pixels
- 相容性問題:
pageXOffset
和pageYOffset
在IE 8
及之前版本的IE
不支援, 使用”document.body.scrollLeft
”and
“document.body.scrollTop
” 來取代
window.pageXOffset
和 window.pageYOffset
,定義了頁面(document
)的相對於視窗原點的水平、垂直位移。因此你能夠定位使用者滾動了多少的滾動條距離。如圖1-7
該屬性也以CSS
的pixels
來度量,同上面的問題,你想要知道在使用者放大視窗的情況下,使用者向上滾動了多少的滾動條。
原理上來說,在使用者放大瀏覽器時,向上滾動了頁面,window.pageXOffset與window.pageYOffset
會改變。但當使用者放大頁面時,瀏覽器會嘗試著儲存使用者當前可見的頁面的元素依然在可見位置。雖然該特性表現得不如預期,但它意味著:在理論上 該情況下 window.pageXOffset
與window.pageYOffset
並沒有改變,被使用者滾出螢幕的CSS
的pixels
幾乎儲存不變。如圖1-8
。
概念:視窗 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
是如何被定義的。我定義了最上面藍色欄目的寬度為width: 100%
。什麼的100%
?當然是
的寬度,同樣是viewport
的寬度,同樣是瀏覽器視窗的寬度。
重點:縮放比例100%
的情況下很正常,現在我們放大瀏覽器,viewport
變得比網站的總寬度更小。對viewport
無影響,但頁面的內容溢位了<html>
元素,但它卻有屬性overflow: visible
。意味著溢位的部分依然會被顯示。
但藍色欄目卻不會溢位。我定義了它寬度為width: 100%
,結果瀏覽器為他賦值寬度為viewport
的寬度。瀏覽器不會在乎這個欄目的寬度是不是過窄了。如圖2-2
頁面寬度 document width
?
我真正想要知道的是頁面內容的總大小,包括超出瀏覽器視窗的部分。到目前為止,據我所知並沒有辦法找到這個值(當然,除非你計算頁面所有部分的寬度包括所有元素的margin
,但是這種計算很容易出錯)。
我開始相信我們需要一個JavaScript
特性對(property pair
)來標示我所謂的頁面寬度 document width
(當然,以CSS
的pixels
來度量)。如圖2-3
如果我們真的感覺對這事兒很煩躁:為什麼不在CSS
中揭露這些值?我期望定義width: 100%
來控制頁面藍色欄目的寬度,它基於頁面的寬度而不是元素的寬度。這似乎很棘手(This is bound to be tricky
),如果這成功的被實現我也不會感倒驚訝。
度量viewport Measuring the view port
document.documentElement.clientWidth與document.documentElement.clientHeight
- 含義:
viewport
的尺寸 - 度量:
CSS
的pixels
- 相容性問題:無
你也許想要知道viewport
的尺寸,他們可以通過document.documentElement.clientWidth
與document.documentElement.clientHeight
來獲取。如圖2-4
如果你熟悉DOM
,你會知道document.documentElement
實際上就是<html>
元素:HTML
文件的根元素。然而viewport
是比<html>
更高階別的元素,打個比喻,它是容納<html>
元素的元素。那會和你是否給元素賦值width
相關(我不建議這麼做,但是卻是可行的)
在那種情況下document.documentElement.clientWidth
與document.documentElement.clientHeight
依然給出了viewport
的尺寸,而不是<html>
元素。(這是特殊的規則只針對這個特殊的元素針對這個特性對。在其餘任何情況下元素使用實際的寬度)如圖2-5
。為<html>
元素賦值25%
。但`document.documentElement.clientWidth
與document.documentElement.clientHeight
的值不變。它雖然貌似從<html>
元素取值,但實際描述的確是viewport
的尺寸。
所以document.documentElement.clientWidth
與document.documentElement.clientHeight
只會給出viewport
的尺寸,而不管<html>
元素尺寸如何改變。
兩個特性對 two property pairs
但是viewport
的尺寸不是也通過window.innerWidth/Height
來描述的麼?嗯,是,也不是。
這兩個特性對有嚴格的區別,幾乎算是吹毛求疵了
window.innerWidth/Height
包含滾動條document. documentElement. clientWidth/Height
不包含
我們能獲取這兩個特性對是因為他們是瀏覽器大戰的殘留。過去Netscape
只支援window.innerWidth/Height
,IE
只支援document.documentElement.clientWidth/Height
。從那時候開始所有其餘瀏覽器都支援這兩個特性。但IE
一直未支援window.innerWidth/Height
。
在桌面系統中,擁有這兩個特性對只是一點小麻煩,但在移動裝置中卻變成了一種祝福。後面我們會看到 。
度量<html>
元素 measuring the <html> element
document.documentElement.offsetWidth/Height
- 含義:
<html>
的尺寸 - 度量:
CSS
的pixels
- 相容性問題:IE用這個值標示viewport的尺寸而非
<html>
如果clientWidth/Height
一直用以標示viewport
的尺寸,我們該如何去獲取<html>
元素的尺寸呢?— document.documentElement.offsetWidth/Height
。如圖2-6
這個特性對真實的讓你訪問塊級元素<html>
元素,如果你為<html>
元素賦值了寬度,offsetWidth
會真實的反應出來。如圖2-7
事件座標 Event coordinates
pageX/Y, clientX/Y, screenX/Y
- 含義:見下文
- 度量:見下文
- 相容性問題:
IE
不支援pageX/Y
,IE
使用CSS pixels
來度量screanX/Y
詳細描述:
pageX/Y
:從<html>
原點到事件觸發點的CSS
的pixels
clientX/Y
:從viewport
原點(瀏覽器視窗)到事件觸發點的CSS
的pixels
screenX/Y
:從使用者顯示器視窗原點到事件觸發點的裝置 的pixels
。
如圖2-8、2-9
和2-10
9
成可能你會用到pageX/Y
而1
成左右會使用clientX/Y
,screenX/Y
基本沒啥用。
Media
查詢 media queries
mediaqueries
- 含義:見下文
- 度量:見下文
- 相容性問題:
IE
不支援.
最後一點文字關於@media
的css
屬性。出發點很簡單:你可以根據頁面的特定寬度來定義特殊的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/height
和 device-width/device-height
。如圖2-11
device-width/height
使用screen.width/height
來做為的判定值。該值以裝置的pixels
來度量width/height
使用documentElement.clientWidth/Height
即viewport
的值。該值以CSS
的pixels
來度量
到底該使用那個呢?一個很無腦的結果:width
。web
開發中不需要對裝置的寬度感興趣,而width
卻使按照瀏覽器視窗的大小計算的
所以在桌面瀏覽器中使用width
而忘記device-width
。接下來我們會看到在移動裝置中有點凌亂。
總結
在此結束對桌面瀏覽器的特性的簡短討論,第二部分主要涉及移動裝置和其與桌面瀏覽器的重要區別。
接下來是第二部分內容,來源於A tale of two viewports — part two一文。
移動裝置瀏覽器的問題
裝置的寬度是移動裝置瀏覽器和桌面瀏覽器的最大區別。移動裝置的顯示通常比桌面瀏覽器顯示同一網站的內容要少。或者縮放瀏覽器變小導致文字無法閱讀,或者只顯示網站適合裝置大小的部分內容。
移動裝置的螢幕寬度比桌面瀏覽器小,經常最大就400px
寬,而且通常會更小。(有些手機號稱大寬度,但他們確是在說謊 – 或起嘛給了我們一些無用的資訊)
一些中間寬度的pad
裝置(table device
)如iPad
或傳說中HP
的webOS
裝置填補了桌面和移動裝置的缺口,但卻沒有解決根本的問題。網站還是必須在移動裝置上工作,我們不得不讓她們在小螢幕上顯示得表現良好。
問題的風暴中心在於CSS
,特別是viewport
的尺寸。如果我們只是拷貝桌面的樣式到移動裝置,我們的CSS
會醜得崩潰
(假設移動裝置的寬度400px
)我們回到width: 10%
的側邊欄。如果在移動裝置上同理處理,會顯示出40px
寬,實在太窄了。你的可變佈局看起來被可怕的壓扁了。
其中一個解決方式是為移動裝置重新建設一個特殊的網站。即使跳開這些基本的問題:你到底該怎麼處理,現實的問題是隻有很少的站長準備好了加入迎合移動裝置而做的改變。
移動裝置瀏覽器供應商期望他們的客戶端提供最好的可能性體驗,即現在意味著“儘可能的像桌面瀏覽器”。因此許多處理手段是必須的。
兩種viewport
因此viewport
太窄,不能很好為你的基本CSS
佈局服務了。最顯然的解決方式是讓viewport
更寬。因此這個需求分為了2個方面:虛擬的viewport
(visual viewport
)和佈局的viewport
(layout viewport
)。
George Cummins
在Stack Overflow
上解釋了這個基本概念,猛擊。
想象下layout viewport
是一張大的不能改變大小和角度的圖片。現在你有個更小的框來觀看這張大圖片,這個框被不透明的材料包圍,因而你只能看到大圖片的一部分。你通過這個框子看到的大圖片的部分被稱為虛擬viewport
(visual viewport
)。你能拿著這個框站得離大圖片遠點(使用者的縮小頁面功能),以一次性看到這個大圖片。或者你能站得近點(使用者的放大頁面功能)以看到一部分。你能改變這個框子的方向,但這張大圖片的大小和形狀都不會改變。
你可以參見解釋詳情by Chris。
visual viewport
是當前顯示在螢幕上的部分頁面。使用者會滾動頁面來改變可見部分,或者縮放瀏覽器來改變visual viewport
的尺寸。見圖1-1.
但是CSS
佈局,特別是感性的寬度(percentual widths
)通常是按照layout viewport
來定義,而比visualviewport
寬很多。
然而<html>
元素的寬度繼承於layout viewport
,你的CSS
應預先準備著需要處理的螢幕(layout viewport
)是不是遠遠超過手機螢幕寬度。這用以保證你的網站外觀特性而恰如在桌面瀏覽器上一樣。
layout viewport
到底有多寬?每個瀏覽器都不同。iPhone
上的Safari
使用980px
、Opera 850px
,安卓的Webkit
核心800px
,IE 974px
。
一些瀏覽器有特別的特性:
- 塞班
webkit
試著儲存layout viewport
和visual viewport
同樣寬度。因此,定義百分比寬度的元素會變得巨難看。當然,如果頁面有特定的寬度而不是適合visual viewport
的寬度,那麼該寬度的最大值會被設定為850px
- 三星的
WebKit
(bada)上)會設定layout viewport
和最寬的元素一樣寬 - 黑莓上
layout viewport
和visual viewport
在100%
縮放時一樣寬。
縮放 Zooming
兩種viewports
都以CSS
的 pixels
來度量。當你通過縮放改變visual viewport
時,layout viewport
儲存不變。
理解layout viewport
為了理解layout viewport
的尺寸,我們先看下頁面完全縮小時發生了什麼。許多移動裝置瀏覽器在初始預設開啟以最小縮放模式開啟網站。(即在手機螢幕上展示完整寬度的頁面)。如圖1-2
.
重點:瀏覽器已經選擇好他們的layout viewport
的尺寸,它完整的覆蓋了最小縮放模式下的移動瀏覽器的螢幕。
這時候layout viewport
的寬度高度和最小縮放模式下能在頁面上顯示的內容的寬度高度一致。即便使用者縮放,它依然儲存不變。如圖1-3
layout viewport
寬度通常儲存不變。如果你旋轉你的手機,visual viewport
改變,但瀏覽器會縮放頁面以自適應,以達到layout viewport
再次和visual viewport
同樣寬。如圖1-4
。
這影響到了layout viewport
的高度,它突然變得比豎著模式更小(portrait model
肖像模式),但web
開發者並不關心高度,只在乎寬度。如圖1-5.
度量layout viewport
document.documentElement.clientWidth/Height
的尺寸
- 含義:
layout viewport
尺寸 - 度量:
CSS
的pixels
- 完整支援:
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
旋轉只關係到高度,而不是寬度。如圖1-7
度量visual viewport
window.innerWidth/Height
- 含義:
visual viewport
尺寸 - 度量:
CSS
的pixels
- 完整支援:
iPhone, Symbian, BlackBerry
問題:
FireFox
和Opera
以裝置的pixels
返回該數值Android, Bolt, MicroB, 和 NetFront
以CSS
的pixels
返回該數值,且為layout viewport
的值
不支援:
IE
,它使用document.documentElement.offsetWidh/Height
來表示- 三星的
Webkit
核心瀏覽器,僅當在頁面上寫入<meta viewport>
標籤,才正確表示。否則就代表著<html>
的尺寸
- 混亂:
Iris, Skyfire, Obigo
返回的值不知所云
我們使用window.innerWidth/Height
來度量visualvviewport
。顯然,隨著使用者縮放瀏覽器,這值會改變,更多、更少的CSS pixels
放進了螢幕。如圖1-8
很不幸這是一個待完善的部分,許多瀏覽器依然沒有支援對visual viewport
的度量。到現在為止,沒有瀏覽器將該度量儲存在其他地方,我猜測window.innerWidth/Height
會成為標準,albeit
是最強力的支持者。
螢幕 Screen
screen.width and screen.height
- 含義:螢幕尺寸
- 度量:裝置的
pixels
- 完整支援:
Opera Mini, Android, Symbian, Iris, Firefox, MicroB, IE, BlackBerry
問題:
Opera
在Windows Mobile
下只給出橫向尺寸(landscape size
)。在S60
上工作正確。- 三星的
Webkit
核心瀏覽器,僅當在頁面上寫入<meta viewport>
標籤,才正確表示。否則就代表著<html>
的尺寸 iPhone
和Obigo
僅給出豎直尺寸(portrait sizes
)Android, Bolt, MicroB
, 和NetFront
以CSS
的pixels
返回該數值,且為layout viewport
的值
不支援:
IE
,它使用document.documentElement.offsetWidh/Height
來表示 - 三星的Webkit
核心瀏覽器,僅當在頁面上寫入<meta viewport>
標籤,才正確表示。否則就代表著<html>
的尺寸
- 混亂:
Iris, Skyfire, Obigo
返回的值不知所云
和pc
瀏覽器一樣,screen.width/height
標示了裝置螢幕的尺寸,以裝置的pixels
度量。和pc
瀏覽器一樣,作為web
開發人員你永遠不需要這些資訊。你不關心螢幕的物理寬度,而關心當前有多少CSS
的pixels
能供你使用。
縮放等級 Zoom level
無法直接獲取縮放等級,但可以使用screen.width
除以window.innerWidth
來計算。當然,只有這兩個特性被完美支援時才能使用。
幸運的是,縮放等級並不重要。你只需要知道當前有多少CSS
的pixels
能供你使用。你可以從window.innerWidth
獲取這些資訊 – 如果當前瀏覽器支援。
滾動位移 scrolling offset
window.pageX/YOffset
- 含義:見描述
- 度量:
CSS
的pixels
- 完整支援:
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
<html>
元素
document.documentElement.offsetWidth / Height
- 含義:
html
元素的整體尺寸 - 度量:
CSS
的pixels
- 完整支援:
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
給出了元素以CSS
的pixels
度量的尺寸。如圖1-10
Media
查詢 media queries
Mediaqueries
- 含義:以
CSS
的pixels
度量<html>
元素或以裝置 的pixels
度量裝置 - 完整支援:
Opera, iPhone, Android, Symbian, Samsung, Iris, Bolt, Firefox, MicroB.
- 不支援:
Skyfire, IE, BlackBerry, NetFront, Obigo
- 備註: 我只測試了瀏覽器是否從正確的特性對裡提取這些值。而特性對裡的值是否正確並不在這裡進行詳細測試。
media
查詢如同桌面系統一樣。width/height
使用以CSS
的pixels
度量的layout viewport,device-width/height
使用以裝置的pixels
度量的裝置螢幕(device screen
)。
換句話說,width/height
反映document.documentElement.clientWidth/Height
的值, device-width/height
反映screen.width/height
. (所有瀏覽器遵循同樣原理,即使取值是錯誤的)。如圖1-11
.
哪個度量對web
開發人員更有用呢?我也不知道。
我起初認為device-width
更重要,因為它給予了裝置的資訊,我們也許可以使用。例如,你能根據裝置的寬度改變網站的外觀。但是你同樣可以使用<meta viewport>
標籤做到這些。因此使用device-width
並不是必須的。
那麼width
就更有用了麼?也許是。瀏覽器的製造商認為他們給出了一些對網站有用的寬度的細節。但這些內容卻含糊(混亂),因而width media
查詢並不真正給出其餘資訊。
所以我沒有做決定。現在我認為media
查詢在標識網站處於桌面瀏覽器、pad
瀏覽器或手機瀏覽器方面很重要,而在區別不同pad
和手機裝置方面並不有用。
事件座標 Event coordinates
Eventcoordinates
- 含義:見下文
- 度量:見下文
- 完整支援:
Symbian, Iris
問題:
Opera
只有pageX/Y
,但滾動頁面過遠時這個值會出錯。- 在
iPhone, Firefox, 和 BlackBerry
上clientX/Y
和pageX/Y
相等 - 在
Android
和MicroB screenX/Y
和clientX/Y
相等,也就是它們以CSS
的pixels
度量螢幕尺寸 - 在
FireFox
裡screenX/Y
值不正確 IE, BlackBerry,
和Obigo
不支援pageX/Y.
NetFront
所以三個值都是screenX/Y
.Obigo clientX/Y
是screenX/Y
.Samsung WebKit
總是返回pageX/Y
.
- 未測試:
Opera Mini,Bolt,Skyfire
事件座標在桌面瀏覽器上多多少少是支援的。不幸的是,移動裝置上在所測試的12個主流瀏覽器中只有Symbian
`WebKit 和
Iris`完全正確的支援這3個座標特性。其餘瀏覽器多多少少都存在問題。
pageX/Y
,該特性依然是基於頁面的CSS pixels
度量的值,如圖在桌面瀏覽器一樣,它是三個特性裡面最有用的。如圖1-12
clientX/Y
是基於visual viewport
的,以CSSpixels
度量的值. 這樣做比較靠譜,雖然我不是很確信這樣計算的好處。
screenX/Y
基於裝置螢幕以裝置的pixels
度量的值。顯然,它使用和clientX/Y
同樣的參考,而裝置的pixels
沒什麼用。所以我們不需要在意screenX/Y
,同在桌面瀏覽器一樣,每個bit
都是沒用的。如圖1-13.
viewport
的meta
標籤 meta viewport
Meta viewport
- 含義:設定
layout viewport
的寬度 - 度量:
CSS
的pixels
- 完整支援:
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.
比如,開啟PC
端百度頁面,頁面沒有設定Meta viewport
,會由於移動裝置的螢幕一般都比PC
小很多,webkit
瀏覽器會將一個較大的“虛擬”視窗對映到移動裝置的螢幕上,預設的虛擬視窗為980
畫素寬(目前大部分網站的標準寬度),然後按一定的比例(3:1
或2:1
)進行縮放。也就是說當我們載入一個普通網頁的時候,webkit
會先以980
畫素的瀏覽器標準載入網頁,然後再縮小,注意這個縮小是一個全域性縮小,也就是頁面上的所有元素都會縮小,縮小這個頁面以在一屏的寬度上顯示
使用者會立馬放大頁面,雖然會起到效果,但絕大多數瀏覽器會儲存元素完整的寬度(保持元素定位的不變),而導致閱讀困難(文字超過螢幕),如圖2-2
比如,上述例子,頁面在放大後,內容會超過螢幕
(唯一不同的是Android
下的Webkit
核心瀏覽器,他會剪短長串文字的html
元素,以讓他們適應螢幕。這簡直太有才了,我覺得其餘所有瀏覽器都應該複用這個特性。我會在再以後全面的寫這方面內容)
現在你可以嘗試著設定htm{width: 320px}
。現在<html>
元素收縮,隨之所有的會計元素都佔有100%
的<html>
寬度:320px
。當使用者放大瀏覽器顯示時這樣做工作得挺好,但在最初載入時的縮小顯示下,使用者感覺很糟糕,因為頁面幾乎沒內容。如圖2-3
.
為了解決這個問題,Apple
引入了meta viewport
。當你設定<meta name="viewport" content="width=320">
,你網站的layout viewport
變成了320px
。頁面的初始狀態就很正確了。如圖2-4
你能任意設定layoutwidth
的寬度,甚至包括device-width
。device-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-width
為320
,我一點都不會驚訝。或許最終device-width
會直接意味著320px
。
總結
為什麼要設定layout viewport
為ideal viewport
呢?比如iPhone6
的理想ideal viewport
的寬度是375px
。
如果不設定meta viewport
,預設會以980px
或者800px
的layout 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 viewport
為320px
的頁插入了一個1500px
元素,如果我們為<html>
設定了overflow: visible
時,它會超出。是否意味著實際的viewport
能比layout viewport
更寬?此外,這種情況發生時一箇舊的Android
裝置(Nexus One
)擴大HTML
元素。這是個好主意麼?