摘要:影響著其中元素的尺寸和定位。在標準中,元素的稱為。當的寬度高度使用百分數的值時,這個百分數的基準就是的尺寸。例子其中就溢出了的區域。造成以上不同的原因是,在桌面端的縮放和在移動端的縮放有不同的性質。這兩個數值的單位是設備獨立像素。
前言
本篇文章修改、整理自我以前寫的一篇文章。
在閱讀這篇文章之前,你需要了解設備像素、邏輯像素(設備獨立像素)和CSS像素的區別,見我的前一篇文章理解設備像素、設備獨立像素和css像素。
在經典文章A tale of two viewports中,作者定義了兩種視口:
layout viewport 包含了頁面中的所有內容,瀏覽器已經計算好了layout viewport中的所有樣式。
visual viewport 用戶看到的的瀏覽窗口(在CSS標準中被稱為viewport)。如果頁面內容溢出了visual viewport,用戶需要移動visual viewport(滾動)才能看完頁面中的所有內容。visual viewport只是一個屏幕上的一個“窗口”,用戶通過這個窗口來觀察頁面。
溢出、滾動條的原理,我總結在了另一篇文章中:css溢出機制探究。
在討論layout viewport、visual viewport的尺寸的時候,我們應該使用CSS像素為單位,而不是設備獨立像素。因為我們關心的是它們能容納多大的元素、多少個元素,這些元素的大小都是通過CSS來定義的。
在這篇文章,我們從CSS2.1標準(主要是8、9、10、11章)出發,更加規范地討論這些內容。
initial containing block(layout viewport)與 visual viewport首先需要先了解一下containing block。containing block影響著其中元素的尺寸和定位。比如我們都知道position:absolute的元素是相對于【最近已定位祖先】來定位的,其背后的原因是:這個元素的盒子(box)的containing block由【最近已定位祖先的padding edge】產生。詳見MDNLayout and the containing block。
在CSS標準中,元素的containing block稱為initial containing block。其他文章所說的layout viewport其實就是initial containing block。后面我將混用這兩個詞。
initial containing block的尺寸initial containing block的尺寸有什么用?它可以決定元素的尺寸。當的寬度、高度、padding、margin使用百分數的值時,這個百分數的基準就是initial containing block的尺寸。
padding、margin使用百分數值的時候都是相對于containing block的width計算的,包括xxx-top、xxx-bottom!
元素是一個block element,與其他的block element一樣,它的寬度默認為containing block的100%(對于就是initial containing block的100%),它的高度默認由子元素撐開(除非明確設置了高度)。
那么initial containing block的尺寸是怎么確定的呢?
桌面瀏覽器在桌面瀏覽器中,initial containing block的尺寸等于visual viewport的尺寸。
為了避免混淆,在這篇文章都使用visual viewport來指代瀏覽窗口。
以下例子驗證了,initial containing block的尺寸是等于瀏覽窗口的。并且我們可以利用它,來元素的width、height、padding(margin同理):
移動端瀏覽器test
在移動端瀏覽器上,layout viewport的尺寸有一些不同:現在大部分的移動端瀏覽器都有2種模式:“查看桌面版網站”和“查看移動版網站”:
在“查看桌面版網站”模式下,瀏覽器會將layout viewport的設置為一個預定義尺寸,寬度一般是980或1024個CSS像素,高度一般是1500以上,不管visual viewport的尺寸是多少。
在“查看移動版網站”模式下(默認處于這個模式),瀏覽器瀏覽器會根據viewport meta tag的信息來決定layout viewport的尺寸。如果沒有viewport meta tag,則瀏覽器會認為這個網站沒有針對小屏設備進行優化,因此表現與“查看桌面版網站”模式相同。
常用的viewport meta tag是。它告訴“查看移動版網站”模式下的瀏覽器,將layout viewport的寬度(CSS像素)設為設備的寬度(設備獨立像素,一般是360px左右)。這樣,在縮放為100%的情況下(CSS像素大小=設備獨立像素大小),屏幕恰好能裝下layout viewport,從而不會出現橫向滾動條。
可以看出,在移動端瀏覽器,不管處于哪種模式,不管有沒有viewport meta tag,layout viewport的尺寸在加載以后就固定了。
內容可以溢出 initial containing block(layout viewport)不要覺得"initial containing block"名字聽起來很厲害,就肯定會將所有內容包含在其區域內。就像其他普通的containing block,頁面中的內容完全可以溢出它。比如絕對定位、overflow:visible。
例子:
test viewport boxout
其中div.out就溢出了initial containint block的區域。
由于有內容溢出了visual viewport,因此在visual viewport上出現了橫向滾動條。visual viewport上的滾動條在css溢出機制探究中討論。
縮放、調整瀏覽器窗口大小的時候,會改變visual viewport的尺寸(用可容納的CSS像素數量來衡量):
在調整縮放比例的時候,瀏覽器窗口可容納的設備獨立像素數量不變,而CSS像素的大小改變了,因此visual viewport可容納的CSS像素數量也改變;
在調整瀏覽器窗口大小的時候,CSS像素的大小不變,而瀏覽器窗口可容納的設備獨立像素數量改變了,因此visual viewport可容納的CSS像素數量也改變。
桌面瀏覽器在桌面瀏覽器中,layout viewport(initial containing block)始終保持與visual viewport尺寸相同(這是為了防止出現橫向滾動條,見我上一篇文章對page zoom的解釋),因此當你通過縮放、調整瀏覽器窗口大小來改變visual viewport的大小時,layout viewport(initial containing block)也會隨之改變。
比如,你在桌面端增大縮放比例,visual viewport會縮小,initial containing block隨之縮小,這就是為什么我們在桌面端縮放可能會造成布局錯亂。(順便提一下,這個問題的簡單解決方案是在HTML元素上設置min-width,防止HTML元素跟著initial containing block一起變小,不過會出現橫向滾動條。復雜解決方案:移動端適配)
例子+注釋:
test
以上例子中,通過級聯的百分數寬度做到了響應式寬度,即,元素的寬度由客戶端的寬度動態決定(在這個例子中是
用桌面瀏覽器打開以上例子,隨便改變瀏覽器窗口大小、改變縮放比例,你會發現
在移動端瀏覽器,不管處于哪種模式,不管有沒有viewport meta tag,layout viewport的尺寸(以CSS像素為單位)在頁面加載以后就固定了。無論用戶如何縮放、調整瀏覽器窗口大小(這在手機上似乎做不到),layout viewport的尺寸都不會改變。
因此,不管你在移動端瀏覽器如何縮放,頁面布局都不會改變。
“layout viewport的尺寸在頁面加載以后就固定了”,這個歸納有一個例外:用戶可以在加載好頁面以后切換橫屏、豎屏模式,從而meta viewport tag中的device-width發生改變,從而layout viewport寬度改變。
造成以上不同的原因是,在桌面端的縮放和在移動端的縮放有不同的性質。見我在上一篇文章的討論。
media query使用media query查詢width、height的時候(比如@media screen and (max-width: 500px) {...}),查到的是layout viewport的尺寸,并且px指的是CSS像素。在桌面端和移動端都是如此。
MDN 文檔也指出了這一點:... if the virtual viewport(也就是這里所說的layout viewport) is 980px for example, media queries that kick in at 640px or 480px or less will never be used, limiting the effectiveness of such responsive design techniques.
例子:
test1
這個例子中,在桌面瀏覽器,通過改變瀏覽器窗口大小或者改變縮放比例,都能造成媒體查詢結果的改變。前面已經解釋過了,這兩個操作都會造成layout viewport尺寸的改變。
例子為了讓讀者明白meta viewport、媒體查詢出現的原因,這里舉一個例子:
有很多網站沒有針對移動端進行優化。對于這些網站,如果在移動端上將layout viewport的尺寸設置為visual viewport的尺寸(寬度為360CSS像素左右),那么排版可能會完全亂掉(意料之外的換行、溢出)。為了能正確顯示這種網站的排版,如果沒有meta viewport的指示,移動端瀏覽器將layout viewport的尺寸設為與電腦瀏覽器一樣,比如980px(單位:CSS像素)。由于手機的屏幕邏輯像素寬度一般只有300~400邏輯像素,因此需要將多個css像素由1個邏輯像素顯示(也就是縮小,不要忘記縮放比例=css像素邊長/邏輯像素邊長),通過縮小css像素讓手機屏幕顯示的css像素與網頁的css像素一樣多。
但是這會引發一個問題:字體小得難以閱讀。用戶閱讀的時候又不得不用手指將縮放比例調整到100%左右(一個設備獨立像素顯示一個css像素,對于我的手機來說,水平方向只有360個設備獨立像素),這個時候visual viewport只顯示layout viewport的一部分了。閱讀的時候需要橫向、縱向滾動。
雖然能夠閱讀網站內容,但這依然是一種非常差的用戶體驗。
適配移動端的時候,先使用來定義layout viewport的寬度,然后通過媒體查詢來為不同的layout viewport定義不同的CSS排版。以下是瀏覽的效果(使用“查看移動版網站”模式):
現在的字體大小合適了,網頁的排版變化了,沒有元素橫向溢出,沒有橫向滾動條,在移動端上的閱讀體驗更好。
上一篇文章說過的screen.width/height:整個屏幕的寬度和高度。這兩個數值的單位是設備獨立像素。這兩個數值不隨頁面縮放、瀏覽器窗口大小而改變,在前端開發的過程中可以認為是固定不變的(除非你通過操作系統改變屏幕的分辨率)。這兩個數值是操作系統決定的,由于設備獨立像素:設備像素經常不等于1:1,實際屏幕物理像素的分辨率不一定是screen.width×screen.height。
在上圖中列出了iphone各代的設備分辨率(物理分辨率)和邏輯分辨率,我們只需要看這兩行。
設備分辨率就是屏幕上的物理像素的數量,當手機廠商宣傳自己的屏幕有多么清晰銳利的時候,相互攀比的就是這個數值。
邏輯分辨率就是screen.width/height。為什么iphone3GS以后的iphone都要把這個值設為實際屏幕分辨率的1/2或1/3呢?因為隨著屏幕上塞進越來越多的物理像素,屏幕大小的變化卻不那么明顯,因此像素密度也越來越高。如果還讓邏輯分辨率:真實屏幕分辨率=1:1,那么12px的字體就會越來越小,影響閱讀體驗。因此,后續的iphone用4個物理像素(甚至9個像素)組合成一個“邏輯像素”。這樣,即使物理像素越來越小,每一個“邏輯像素”的大小變化不大。瀏覽器可以放心地使用邏輯像素來衡量大小,而不用擔心真實大小在不同的顯示器上出現嚴重偏差。
2. window.innerWidth/Heightvisual viewport的大小,也就是瀏覽器內容窗口的大小,不包括菜單欄、地址欄、狀態欄等,但是包括滾動條。單位是CSS像素。通過這個屬性你可以知道,當前的瀏覽器窗口可以容納多少個css像素。當用戶放大的時候這個數值會減少(因為css像素變大了),當用戶縮小的時候這個數值增大。縮放改變瀏覽器窗口都會改變這個屬性的值。
與之對應的,window.outerWidth/outerHeight給出整個瀏覽器窗口的大小(包括各種欄),但是單位是設備獨立像素。3. document.documentElement.clientWidth/Height
Layout Viewport(initial containing block)的尺寸。注意,Layout Viewport沒有滾動條(根據css溢出機制探究中的討論,只有元素或者visual viewport才能擁有滾動條)。單位是CSS像素。
document.documentElement指的是html元素,通常Element.clientWidth應該給出元素的內容區域的大小,但是document.documentElement.clientWidth/Height并不衡量html元素的大小,這是一個特例。各個瀏覽器都遵循著這個約定。并且,這個約定正在被標準化。4. document.documentElement.offsetWidth/Height
元素的尺寸。前面已經討論過元素的尺寸是如何計算的了,默認情況下的寬度始終與Layout Viewport寬度相同。單位是CSS像素。元素的高度由內容撐開。
5. window.pageXOffset/pageYOffset滾動距離,描述visual viewport已經向右、向下滾動了多少個像素。也可以理解為visual viewport相對于layout viewport的偏移值。單位是CSS像素。
它們分別有1個別名(前者的兼容性更好些):
window.pageXOffset == window.scrollX; // always true window.pageYOffset == window.scrollY; // always true
此外,由于Element上就有獲取內容滾動的scrollLeft、scrollTop屬性(所有Element都可以使用),因此還有:
window.pageXOffset === document.documentElement.scrollLeft; // always true window.pageYOffset === document.documentElement.scrollTop; // always true
當用戶進行縮放的時候,瀏覽器會盡量保證:原先在內容區頂部的元素,在縮放以后依然在內容區頂部,看以下例子:參考資料
放大前:
放大后:
原本數字3在頂部,放大后3依然在頂部。window.pageYOffset大致相同。大致相同的原因是CSS像素數量不隨著縮放而變化,原本在上方的內容高度有多少個CSS像素,放縮以后依然是多少個CSS像素。至于為什么不是完全相同,是因為"原先在內容區頂部的元素,在縮放以后依然在內容區頂部"這一機制無法完美地做到。
https://www.quirksmode.org/mo...
https://www.quirksmode.org/mo...
https://www.quirksmode.org/bl...
相關規范的進展一些比css2.1更新的文檔(但是還沒有正式作為Recommondation規范):
CSS Snapshot CSS3開始,CSS不再由一份大而全的文檔來定義,而是分成多個模塊、由多個文檔來定義,方便各個技術的獨立演化。這份文檔收集了當前隸屬于CSS的、相對穩定的文檔。
CSS Box Model Module Level 3 盒模型文檔。該文檔的內容與CSS2.1相比沒有變化。
CSS Positioned Layout Module Level 3 布局、層疊文檔。
CSS Display Module Level 3 CSS formatting box tree文檔。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/116951.html
摘要:設備像素設備分辨率設備像素也叫物理像素。從圖中可以驗證,橫縱方向的設備像素數量恰好是設備獨立像素的倍。像素與設備獨立像素的關系縮放比例就是像素邊長設備獨立像素邊長。因為的寬度沒有改變,無論以什么單位衡量設備像素設備獨立像素還是像素。 這篇文章是我在我的舊博客上發過的文章,最近又碰到這個問題,整理修改了一下發到這里。 像素單位 像素單位有設備像素、邏輯像素和CSS像素3種。 設備像素(d...
閱讀 1668·2021-11-19 09:40
閱讀 2923·2021-09-24 10:27
閱讀 3214·2021-09-02 15:15
閱讀 1876·2019-08-30 15:54
閱讀 1202·2019-08-30 15:54
閱讀 1368·2019-08-30 13:12
閱讀 625·2019-08-28 18:05
閱讀 2793·2019-08-27 10:53