視口概念

本文闡述了視口的概念——它是什麼,以及它在 CSS、SVG 和移動裝置方面的影響。本文定義了初始視口和實際視口,並區分了視覺視口佈局視口

什麼是視口?

視口是使用者代理的一項功能,用於為連續媒體建立初始包含塊。

通用的視口術語通常指計算機圖形學中當前正在檢視的區域。在 Web 瀏覽器術語中,它通常與瀏覽器視窗相同,不包括 UI、選單欄等。它是你正在檢視的文件部分。

文件載入時,視口會經歷兩個階段:

初始視口

初始視口指的是在使用者代理樣式、HTML <meta> 標籤或 CSS 樣式覆蓋其大小之前,UA 的視窗或可視區域。初始視口的大小基於視窗或可視區域的大小,而不是內容。全屏使用者代理的初始視口大小會因裝置和方向而異,但對於同一裝置在同一方向下,其大小總是相同的。

實際視口

實際視口是在處理了視口 <meta> 標籤後得到的視口。為大視口設計的內容在小視口中檢視時可能會出現各種錯誤,包括意外換行、內容被裁剪以及滾動容器大小不正確。視口元標籤提供了有關視口初始大小的提示。實際視口的大小由其 content 屬性定義。如果省略此標籤,一些移動瀏覽器會使用固定的初始包含塊寬度來渲染內容,通常是 980px。它們將實際視口的寬度設定為此值,然後縮小內容以適應它,使得 CSS 畫素尺寸小於實際畫素。

像本文這樣的文件可能會很長。你的視口是當前可見的所有內容;值得注意的是,“什麼是視口”部分,或許還有一些導航選單。視口的大小取決於螢幕的大小、瀏覽器是否處於全屏模式,以及瀏覽器是否被放大。視口外的內容,比如本文件中的“參見”部分,在滾動到檢視中之前可能不會在螢幕上顯示。

  • 在較大的顯示器上,應用程式不一定是全屏的,此時視口就是瀏覽器視窗的大小。
  • 在大多數移動裝置上以及瀏覽器處於全屏模式時,視口就是整個螢幕。
  • 在全屏模式下,視口是裝置螢幕,視窗是瀏覽器視窗(可以和視口一樣大,也可以更小),而文件是網站(可能比視口高得多或寬得多)。

對於分頁媒體,初始包含塊基於頁面區域。頁面區域可以透過 @page 規則設定。

總而言之,視口基本上是文件當前可見的部分。

視口大小是可變的

視口的寬度並不總是視窗的寬度。如果你在 Chrome 或 Firefox 中查詢視窗和文件的寬度或高度,你可能會得到:

js
document.documentElement.clientWidth; /* 1200 */
window.innerWidth; /* 1200 */
window.outerWidth; /* 1200 */
js
document.documentElement.clientHeight; /* 800 */
window.innerHeight; /* 800 */
window.outerHeight; /* 900 */

有幾個 DOM 屬性可以幫助你查詢視口大小以及其他類似的長度:

  • 文件元素的 Element.clientWidth 是文件在CSS 畫素中的內部寬度,包括內邊距(但不包括邊框、外邊距或垂直捲軸,如果存在的話)。這就是視口的寬度
  • Window.innerWidth 是瀏覽器視窗視口的寬度(以 CSS 畫素為單位),包括(如果渲染的話)垂直捲軸。
  • Window.outerWidth 是瀏覽器視窗外部的寬度,包括所有的視窗介面元素

在一個實驗中,觀察到 innerWidthouterWidth 是相同的,但 outerHeightinnerHeight 高 100px。這是因為 outerHeight 包括了瀏覽器介面元素:測量是在一個位址列和書籤欄總高度為 100px 的瀏覽器上進行的,但視窗的左側或右側沒有介面元素。

innerHeightinnerWidth 內的區域通常被認為是佈局視口。瀏覽器介面元素不被視為視口的一部分。

放大後,Firefox 和 Chrome 都會報告 innerWidthclientWidth 新的 CSS 畫素大小。outerWidthouterHeight 返回的值取決於瀏覽器:Firefox 報告以 CSS 畫素為單位的新值,但 Chrome 返回以預設畫素大小為單位的長度。放大後你可能會得到:

js
document.documentElement.clientWidth; /* 800 */
window.innerWidth; /* 800 */
window.outerWidth; /* 800 in Firefox, 1200 in chrome */
js
document.documentElement.clientHeight; /* 533 */
window.innerHeight; /* 533 */
window.outerHeight; /* 596 in Firefox, 900 in chrome */

視口最初是 1200 x 800 畫素。放大後,視口變為 800 x 533 畫素。這就是佈局視口。帶有以下樣式的粘性頁首或頁尾將分別固定在佈局視口的頂部和底部。

css
body > header {
  position: fixed;
  top: 0;
}
body > footer {
  position: fixed;
  bottom: 0;
}

我們使用鍵盤放大時得到了 800 x 533 的尺寸。頁首和頁尾緊貼著視窗的頂部和底部。但如果我們在平板電腦上進行雙指縮放呢?如果手機上彈出了動態鍵盤呢?

佈局視口和視覺視口

Web 中存在兩個視口,即佈局視口視覺視口。視覺視口是網頁在瀏覽器中當前可見的部分,並且可以改變。當用戶雙指縮放頁面、彈出動態鍵盤,或者當一個先前隱藏的位址列變得可見時,視覺視口會縮小,但佈局視口保持不變。

如上所述,固定的粘性頁首或頁尾會粘在佈局視口的頂部和底部,因此當我們用鍵盤放大時,它們仍然在檢視中。如果你進行雙指縮放,佈局視口可能不會完全可見。如果你從佈局視口的中間放大,內容會向四個方向擴充套件。如果你有粘性頁首或頁尾,它們仍然會粘在佈局視口的頂部或底部,但它們可能不會在裝置螢幕的頂部和底部可見——而裝置螢幕就是視覺視口。視覺視口是佈局視口當前可見的部分。如果你向下滾動,你正在改變視覺視口的內容,並將佈局視口的底部帶入檢視,從而顯示粘性頁尾,然後它將保持粘在底部。

視覺視口是螢幕的可視部分,不包括螢幕鍵盤、雙指縮放區域之外的區域,或其他不隨頁面尺寸縮放的功能。視覺視口的大小與佈局視口相同或更小。

對於包含 iframe、object 或外部 SVG 的頁面,包含頁面和每個被包含的檔案都有其自己獨特的視窗物件。只有頂層視窗有一個可能與佈局視口不同的視覺視口。對於被包含的文件,視覺視口和佈局視口是相同的。

CSS

上面描述的佈局視口和視覺視口並不是你將遇到的唯二的視口。任何在佈局視口內完全或部分顯示的子視口都被視為視覺視口。

我們通常認為 widthheight 媒體查詢是相對於瀏覽器視窗的寬度和高度的。它們實際上是相對於視口的,在主文件中視口是視窗,但在像 object、iframe 和 SVG 這樣的巢狀瀏覽上下文中,它是元素父級的固有大小。在 CSS 中,我們也有基於視口大小的長度單位。一個 vh 單位是佈局視口高度的 1%。同樣,vw 單位是佈局視口寬度的 1%。

<iframe>

<iframe> 內部,視覺視口是 iframe 的內部寬度和高度的大小,而不是父文件的大小。你可以為 iframe 設定任何高度和寬度,但整個文件可能不會都可見。

如果你在 iframe 文件的 CSS 中使用視口長度單位1vh 將是 iframe 高度的 1%,1vw 將是 iframe 文件寬度的 1%。

css
iframe {
  width: 50vw;
}

如果 iframe 被設定為 50vw,它將是我們上面例子中 1200px 父文件寬度的 50%,即 600px,其中 1vw6px。放大後,iframe 縮小到 400px1vw 變為 4px

iframe 文件中基於寬度的媒體查詢是相對於 iframe 的視口的。

css
@media screen and (width >= 500px) {
  p {
    color: red;
  }
}

如果上述 CSS 包含在 iframe 中,當用戶放大時,段落將變為紅色,但此樣式在未放大狀態下不適用。

SVG

SVG 文件中,視口是 SVG 影像的可見區域。你可以為 <svg> 設定任何高度和寬度,但整個影像可能不會都可見。可見的區域稱為視口。視口的大小可以使用 <svg> 元素的 width 和 height 屬性來定義。

html
<svg height="300" width="400"></svg>

在這個例子中,視口的寬高比為 3:4,預設情況下是 400x300 單位,一個單位通常是一個 CSS 畫素。

SVG 還有一個透過 viewBox 屬性定義的內部座標系統,這與本次視口的討論無關。

如果你在 HTML 中包含一個 SVG 檔案,SVG 的視口是初始包含塊,即 SVG 容器的寬度和高度。在 SVG 的 CSS 中使用 @media 查詢是相對於該容器的,而不是瀏覽器。

css
@media screen and (400px <= width <= 500px) {
  /* CSS goes here */
}

通常,當你編寫上述媒體查詢時,如果視口(通常是瀏覽器視窗)在 400px 和 500px 之間(含),則應用樣式。SVG 中的寬度媒體查詢是基於 SVG 所在的元素——如果源是 SVG 檔案,則是 <img>;如果 SVG 直接包含在 HTML 中,則是 SVG 本身;或者如果父元素被分配了寬度,則是父元素——而不是視口的寬度。由於上述媒體查詢在我們的 SVG 檔案中,如果 SVG 容器在 400px 和 500px 之間,則應用 CSS。

JavaScript

Visual Viewport API 提供了一種查詢和修改視覺視口屬性的機制。

Viewport API 提供了一種查詢和修改視覺視口屬性的機制。

移動端視口

移動裝置有各種形狀和大小,螢幕具有不同的裝置畫素比。移動瀏覽器的視口是可以看到 Web 內容的視窗區域,它不一定與渲染頁面的大小相同。移動瀏覽器在一個虛擬視窗或視口中渲染頁面,通常為 980px,這通常比螢幕更寬,然後將渲染結果縮小以便可以一次性看到全部內容。然後使用者可以平移和縮放以檢視頁面的不同區域。例如,如果一個移動螢幕的寬度為 320px,一個網站可能會以 980px 的虛擬視口進行渲染,然後它將被縮小以適應 320px 的空間,這取決於設計,對許多人(如果不是所有人)來說都是難以辨認的。為了告訴移動瀏覽器使用視口寬度而不是預設的 980px 作為螢幕寬度,開發者可以包含一個視口元標籤,如下所示:

html
<meta name="viewport" content="width=device-width" />

width 屬性控制視口的大小。最好將其設定為 device-width,即螢幕在 100% 縮放比例下的 CSS 畫素寬度。還有其他屬性,包括 maximum-scaleminimum-scaleuser-scalable,它們控制使用者是否可以放大或縮小頁面,但預設值對可訪問性和使用者體驗是最好的,因此可以省略這些屬性。

另見