口(viewport)代表當前可見的計算機圖形區域。在Web瀏覽器術語中,通常與瀏覽器窗口相同,但不包括瀏覽器的UI, 菜單欄等——即指你正在瀏覽的文檔的那一部分。
一般我們所說的視口共包括三種:布局視口、視覺視口和理想視口,它們在屏幕適配中起著非常重要的作用。
布局視口(layout viewport):當我們以百分比來指定一個元素的大小時,它的計算值是由這個元素的包含塊計算而來的。當這個元素是最頂級的元素時,它就是基于布局視口來計算的。
所以,布局視口是網頁布局的基準窗口,在PC瀏覽器上,布局視口就等于當前瀏覽器的窗口大?。ú话╞orders 、margins、滾動條)。
在移動端,布局視口被賦予一個默認值,大部分為980px,這保證PC的網頁可以在手機瀏覽器上呈現,但是非常小,用戶可以手動對網頁進行放大。
我們可以通過調用document.documentElement.clientWidth / clientHeight來獲取布局視口大小。
視覺視口(visual viewport):用戶通過屏幕真實看到的區域。
視覺視口默認等于當前瀏覽器的窗口大?。òL動條寬度)。
當用戶對瀏覽器進行縮放時,不會改變布局視口的大小,所以頁面布局是不變的,但是縮放會改變視覺視口的大小。
例如:用戶將瀏覽器窗口放大了200%,這時瀏覽器窗口中的CSS像素會隨著視覺視口的放大而放大,這時一個CSS像素會跨越更多的物理像素。
所以,布局視口會限制你的CSS布局而視覺視口決定用戶具體能看到什么。
我們可以通過調用window.innerWidth / innerHeight來獲取視覺視口大小。
布局視口在移動端展示的效果并不是一個理想的效果,所以理想視口(ideal viewport)就誕生了:網站頁面在移動端展示的理想大小。
如上圖,我們在描述設備獨立像素時曾使用過這張圖,在瀏覽器調試移動端時頁面上給定的像素大小就是理想視口大小,它的單位正是設備獨立像素。
上面在介紹CSS像素時曾經提到頁面的縮放系數=CSS像素 / 設備獨立像素,實際上說頁面的縮放系數=理想視口寬度 / 視覺視口寬度更為準確。
所以,當頁面縮放比例為100%時,CSS像素=設備獨立像素,理想視口=視覺視口。
我們可以通過調用screen.width / height來獲取理想視口大小。
<meta> 元素表示那些不能由其它HTML元相關元素之一表示的任何元數據信息,它可以告訴瀏覽器如何解析頁面。
我們可以借助<meta>元素的viewport來幫助我們設置視口、縮放等,從而讓移動端得到更好的展示效果。
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">
上面是viewport的一個配置,我們來看看它們的具體含義:
Value 可能值 描述 width 正整數或device-width 以pixels(像素)為單位, 定義布局視口的寬度。 height 正整數或device-height 以pixels(像素)為單位, 定義布局視口的高度。 initial-scale 0.0 - 10.0 定義頁面初始縮放比率。 minimum-scale 0.0 - 10.0 定義縮放的最小值;必須小于或等于maximum-scale的值。 maximum-scale 0.0 - 10.0 定義縮放的最大值;必須大于或等于minimum-scale的值。 user-scalable 一個布爾值(yes或者no) 如果設置為 no,用戶將不能放大或縮小網頁。默認值為 yes。
為了在移動端讓頁面獲得更好的顯示效果,我們必須讓布局視口、視覺視口都盡可能等于理想視口。
device-width就等于理想視口的寬度,所以設置width=device-width就相當于讓布局視口等于理想視口。
由于initial-scale=理想視口寬度 / 視覺視口寬度,所以我們設置initial-scale=1;就相當于讓視覺視口等于理想視口。
這時,1個CSS像素就等于1個設備獨立像素,而且我們也是基于理想視口來進行布局的,所以呈現出來的頁面布局在各種設備上都能大致相似。
上面提到width可以決定布局視口的寬度,實際上它并不是布局視口的唯一決定性因素,設置initial-scale也有肯能影響到布局視口,因為布局視口寬度取的是width和視覺視口寬度的最大值。
例如:若手機的理想視口寬度為400px,設置width=device-width,initial-scale=2,此時視覺視口寬度=理想視口寬度 / initial-scale即200px,布局視口取兩者最大值即device-width 400px。
若設置width=device-width,initial-scale=0.5,此時視覺視口寬度=理想視口寬度 / initial-scale即800px,布局視口取兩者最大值即800px。
瀏覽器為我們提供的獲取窗口大小的API有很多,下面我們再來對比一下:
SS 過去只有四個你需要知道的視口單元,它們幾乎可以涵蓋所有可以想象的用例。 然而,隨著時間的推移和技術的變化,這四個視口單元不再足以處理所有用例。 由于CSS 增加了 20 個視口單元,這聽起來很多,但它們被分解為六個主要的視口單元,并帶有三個獨特的修飾符,總共有 24 種組合。
主要的4種視口單元
主要的 CSS 視口單位是 vw、vh、vmin 和 vmax。 您以前可能使用過或看過這些單位,所以我在解釋它們時會盡量簡短。
VW
vw 代表 Viewport Width,代表視口寬度的百分比。 放置在 vw 之前的數字是視口寬度的百分比。 例如,如果您寫了 10vw,那么這將代表視口寬度的 10% 的長度。
視口代表你屏幕的大小,如果你在一個寬度為 1920 像素的大桌面上,10vw 將代表 192 像素。 如果您使用的是寬度為 300px 的手機,那么 10vw 將只有 30px。
VH
vh 代表視口高度,與 vw 完全相同,但它代表高度而不是寬度。 這兩個單元可以組合使用,以輕松地使元素填滿屏幕的整個大小。
VMIN 和 VMAX
vmin 和 vmax 表示最大和最小視口尺寸。 例如,如果您使用的是 300 像素寬和 800 像素高的手機,則 vmin 將代表視口的寬度,而 vmax 將代表設備的高度。 如果您需要根據屏幕的最小/最大尺寸調整元素的大小,這些單位非常有用。 例如,下面的 CSS 將創建一個盡可能大的正方形,而不會在任何方向溢出,因為它永遠不會大于最小屏幕尺寸的 100%。
兩個新的視口單位
CSS 一直在嘗試從嚴格的頂部/底部、左/右、高度/寬度模型轉變為更動態的開始/結束、塊/內聯模型。 此更改的主要原因是它可以讓你更容易地采用不同的編寫方向。 如果您的整個應用程序從水平書寫方向切換到垂直書寫方向,則頂部/底部或寬度/高度的概念不一定意味著相同的事情,因為如果您想在文本上方和下方添加填充,這將被表示 作為垂直書寫系統中的左右填充,而不是填充頂部和底部。 這就是 CSS 添加 vi 和 vb 視口單元的原因。
VI
vi 代表 Viewport Inline,代表文檔的內聯方向。 在水平書寫方向上,這對應于視口的寬度,而在垂直書寫方向上,這表示視口的高度。 記住 inline 方向的簡單方法是記住它與文本的方向相同。 另一種記住這一點的方法是,如果您有兩個彼此相鄰的內聯元素(例如兩個跨度),那么它們堆疊的方向就是您的內聯方向。
VB
vb 代表 Viewport Block,代表文檔的塊方向。 這與 vi 相反,因此在水平書寫方向上,這將對應于視口高度,在垂直文檔中,這將表示視口的寬度。 如果你很難記住這個單元,請記住塊方向始終是塊元素(例如兩個 div)相互堆疊的方向。
視口單位修飾符
到目前為止,我們已經介紹了六種主要類型的視口單元,但是當您的視口可以改變大小時,您可以將三種不同的修改器添加到單元中以使它們表現不同。例如,當您在手機上瀏覽網頁時,您可能會注意到向下滾動時 URL 欄會消失。發生這種情況時,您的視口在技術上會更改大小,因為現在 URL 欄不再占據您的視口的一部分。當前的 CSS 單元無法處理視口大小的這種變化,這就是添加這些修飾符的原因。
這些修飾符是 s、l 和 d。為了使用修飾符,您只需將修飾符放在數字之后和單位之前,例如 10svw。這為 6 個視口單元中的每一個提供了 4 個總組合。大眾、svw、lvw 和 dvw。
到目前為止,我們在本文中介紹的所有內容都沒有使用完全有效的修飾符。當您在單元上不使用修飾符時,例如 10vw 或 10vh,瀏覽器將自動默認使用基于瀏覽器實現的 3 個修飾符之一。
s修飾符
s 修飾符代表 Small 并表示可能的最小視口。 在我們的手機示例中,這將是顯示 URL 欄時視口的大小。 如果您將一個元素設置為 100svh,它將占據屏幕高度的 100%,具體取決于顯示 URL 欄時的屏幕大小。 URL 欄是否可見無關緊要,此單元將始終根據顯示 URL 欄時的視口大小來確定其大小。
l修飾符
l 修飾符代表Large,代表最大可能的視口。 這幾乎與 s 修飾符相反。 在我們的手機示例中,這將是沒有顯示 URL 欄時的視口大小。 如果您將元素設置為 100lvh,則當 URL 欄不顯示時,它會根據屏幕大小占據屏幕高度的 100%。 URL 欄是否可見無關緊要,如果 URL 欄未顯示,此單元將始終根據視口的大小確定其大小,這意味著如果您將元素設置為 100lvh 并且 URL 欄顯示它在技術上將 比屏幕大。
d修飾符
d 修飾符代表動態,代表當前視口大小。 這就像 s 和 l 修飾符的組合。 在我們的手機示例中,無論 URL 欄是否顯示,這始終是當前視口的大小。 如果我們的 URL 欄正在顯示,則 d 修飾符與 s 修飾符大小相同,而如果 URL 欄未顯示 d 修飾符與 l 修飾符大小相同。
在顯示和隱藏 URL 欄之間的過渡期間,此單元將動態縮放大小,因此它始終會填滿所有可用空間。 如果您需要確保元素始終根據視口調整大小,這很好,但可能會很費力,因為隨著大小的不斷變化,它會導致大量重繪。
瀏覽器支持
對于每一個很酷的 CSS 功能,您總是需要考慮瀏覽器支持,不幸的是,瀏覽器對這些新視口單元的支持不是很好。 目前,這些新單元的支持率為 15.2%,并且實際上僅在 Safari 和 Firefox 中得到支持。 缺乏支持的原因是該提案仍處于工作草案階段,這意味著它還處于生命周期的早期階段,距離成為官方 CSS 還很遠。
結論
雖然 24 個單位可能聽起來很多,但實際上只有 6 個單位和三個相對簡單的修飾符。 然而,這些簡單的組合給了我們構建完美 CSS 布局的強大能力。
*CSS Viewport units(視口單位)**在過去幾年已經出現了,隨著時間的推移,越來越多的開發人員開始使用它們。它們的好處在于為我們提供了一種不需要使用J avaScript 就能以動態的方式調整大小的方法。而且,如果它失效,也有很多備用方案。
在本文中,我們將學習 CSS Viewport units(視口單位)以及如何使用它們,并用列舉一些常見問題及其解決方案和用例,讓我們開始吧。
根據CSS規范,視口百分比單位相對于初始包含塊的大小,它是web頁面的根元素。
視口單位為:vw,vh,vmin和vmax。
vw單位表示根元素寬度的百分比。1vw等于視口寬度的1%。
vw單位表示根元素寬度的百分比,1vw等于視口寬度的1%。
假設我們有一個元素與以下CSS:
.element {
width: 50vw;
}
當視口寬度為500px時,50vw計算如下
width = 500*50% = 250px
vh單位表示根元素高度的百分比,一個vh等于視口高度的1%。
我們有一個元素與以下CSS:
.element {
height: 50vh;
}
當視口高度為290px時,70vh計算如下:
height = 290*70% = 202px
大家都說簡歷沒項目寫,我就幫大家找了一個項目,還附贈【搭建教程】。
vmin表示視口的寬度和高度中的較小值,也就是vw 和 vh 中的較小值。如果視口寬度大于其高度,則將根據高度計算該值。
我們以下面的例子為例。
我們有一個橫屏手機,其中有一個元素具有vmin單元。在這種情況下,值將根據視口高度計算,因為它小于寬度。
.element {
padding-top: 10vmin;
padding-bottom: 10vmin;
}
這是vmin的計算方式:
正如你所猜測的,計算結果如下所示
padding-top = (10% of height) = 10% * 164 = 16.4px
padding-bottom = (10% of height) = 10% * 164 = 16.4px
vmax與vmin相反,該值是vw 和 vh 中的較大值。
我們以下面的例子為例。
.element {
padding-top: 10vmax;
padding-bottom: 10vmax;
}
計算結果如下:
padding-top = (10% of width) = 10% * 350 = 35px
padding-bottom = (10% of width) = 10% * 350 = 35px
視口單位基于頁面的根元素,而百分比則基于它們所在的容器。因此,它們彼此不同,但各自都有各自的用處。
CSS 視口單位非常適合響應式排版。例如,我們可以將以下內容用作文章標題:
.title {
font-size: 5vw;
}
標題的font-size將根據視口寬度增加或縮小。就像提供的字體大小是視口寬度的5%一樣。但是,如果沒有適當的測試就直接使用它可能會踩到坑。讓我們看下面的視頻:
體大小變得非常小,這不利于可訪問性和用戶體驗。據我所知,移動設備上的最小字體大小不應該不于14px。在GIF中,不小于10px。
要解決該問題,我們需要為標題提供最小字體大小,可以使用 calc()
.title {
font-size: calc(14px + 2vw);
}
calc()CSS函數將具有一個最小值14px,并在些基礎上添加2vw的值,有了這些,字體大小值就不會變得太小。
另一個需要考慮的重要問題是字體大小在大屏幕上的表現,例如 27” iMac。會發生什么呢?你猜對了,字體大小為95px左右,這是一個很大的值。為了防止這種情況,我們應該在某些斷點上使用媒體查詢并更改字體大小。
@media (min-width: 1800px) {
.title {
font-size: 40px;
}
}
通過重置字體大小,我們可以確保大小不會太大。您可能還需要添加多個媒體查詢,但這取決于你自己,也取決于項目的上下文。
事例地址:https://codepen.io/shadeed/pen/fa989837c6379770cce49f0be6daa3e3
有時,我們需要一個section來獲取100%的視口高度,為此,我們可以使用viewport高度單位。
.section {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
通過添加 height: 100vh,我們可以確保section 高度將采取100%的視口。此外,我們添加了一些flexbox來處理水平和垂直居中的內容。
事例源碼:https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=1100
在大屏幕上,網站內容有時候很少,footer 沒有粘在底部。這很正常,也不被認為是一種不好的做法。但是,還有改進的余地。考慮下面代表問題的示圖:
為了解決這個問題,我們需要給內容(content)一個高度,它等于視口高度- (header + footer)。動態地做到這一點是很困難的,但是使用CSS的視口,這是很容易的。
如果header 和footer的高度是固定的,那么可以將calc()函數和視口單位結合起來,如下所示:
header,
footer {
height: 70px;
}
main {
height: calc(100vh - 70px - 70px);
}
不能保證此解決方案始終有效,尤其是對于footer而言。在我的職業生涯中,我沒有使用固定高度的頁腳,因為在例如不同的屏幕尺寸下,此footer是不可行的。
通過將100vh設置為body元素的高度,然后可以使用flexbox來使main元素占用剩余空間。
body {
min-height: 100vh;
display: flex
flex-direction: column;
{
main {
/* This will make the main element take the remaining space dynamically */
flex-grow: 1;
}
這樣,問題就解決了,無論內容長度如何,我們都有一個粘性footer。
事例源碼:https://codepen.io/shadeed/pen/c735b26b8fa97ee685b38084448b3f85?editors=1100
假設我們有一個作品集來展示我們的響應式設計工作,并且我們有三種設備(移動設備、平板電腦和筆記本電腦)。每個設備包含一個圖像。目標使用 CSS 來響應適配這些頁面。
通過使用CSS網格和視口單位,我們可以使其完全動態的響應式。
<div class="wrapper">
<div class="device laptop"></div>
<div class="device mobile"></div>
<div class="device tablet"></div>
</div>
視口單位也可以用于grid- *屬性,也用于border,border-radius和其他屬性。
.wrapper {
display: grid;
grid-template-columns: repeat(20, 5vw);
grid-auto-rows: 6vw;
}
.mobile {
position: relative;
z-index: 1;
grid-column: 2 / span 3;
grid-row: 3 / span 5;
}
.tablet {
position: relative;
z-index: 1;
grid-column: 13 / span 7;
grid-row: 4 / span 4;
border-bottom: 1vw solid #a9B9dd;
border-right: solid 3vw #a9B9dd;
}
.laptop {
position: relative;
grid-column: 3/span 13;
grid-row: 2 / span 8;
}
/* Viewport units are used for the bottom, left, right, height, and border-radius. Isn't that cool? */
.laptop:after {
content:"";
position:absolute;
bottom: -3vw;
left: -5.5vw;
right: -5.5vw;
height: 3vw;
background-color: #a9B9dd;
border-radius: 0 0 1vw 1vw;
}
事例源碼:https://codepen.io/shadeed/pen/2da0f2b70699769f8de3220ff4465bc6?editors=1100
我注意到一個用例最適合編輯版面。一個子元素,即使父元素的寬度受到限制,它也會占據視口100%的寬度。考慮下面:
.break-out {
width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;
}
讓我們把它分解一下,這樣我們就能一點一點地理解所有這些屬性是如何工作的。
1.添加 width: 100vw
最重要的一步,將圖像的寬度設置為100%的視口。
2.添加 margin-left: -50vw
為了使圖像居中,我們需要給它一個負的邊距,其寬度為視口寬度的一半。
3.添加 left: 50%
最后,我們需要將圖像向右推,其值為父寬度的50%。
事例地址:https://codepen.io/shadeed/pen/828f12b1ef7fa7211584ff5c7b82d2fa?editors=1100
我想到的另一個有趣的用例是使用視口單位來表示元素之間的間距。這可以與margin、top、bottom和grid-gap等值一起使用。使用時,間距將基于視口寬度或高度,這對于使布局更具動態性可能很有用。
對于模態,我們需要將它們從視口頂部推入。通常,使用top屬性進行此操作,并使用百分比或像素值。但是,對于視口單位,我們可以添加一個可以根據視口高度改變的間距。
.modal-body {
top: 20vh;
}
事例地址:https://codepen.io/shadeed/pen/f77a0d58947c64c2b3dadbd887700db5?editors=1100
頁面header 是充當頁面介紹的部分。它通常具有標題和描述,并且其中上下邊緣的高度固定或填充
例如,有以下的CSS的樣式:
.page-header {
padding-top: 10vh;
padding-bottom: 10vh;
}
.page-header h2 {
margin-bottom: 1.5vh;
}
使用vh單位用于頁面標題的 paddding,以及標題下方的邊距。注意間距如何變化!
事例源碼:https://codepen.io/shadeed/pen/43024fa031519e316e95bb3ce47f2b22?editors=1100
該用例是關于頁面標題元素的頂部和底部padding 。當視口較?。ㄒ苿樱r,通常會減少padding。通過使用vmin,我們可以在視口較小尺寸(寬度或高度)的基礎上獲得合適的頂部和底部 padding。
.page-header {
padding: 10vmin 1rem;
}
事例源碼:https://codepen.io/shadeed/pen/f335c2f43b960a2c70ea057228ddc5b9?editors=0100
我們可以使用vw單位創建響應元素,以保持其縱橫比,而不管視口大小如何。
首先,需要先確定所需的縱橫比,對于此示例,使用9/16。
section {
/* 9/16 * 100 */
height: 56.25vw;
}
事例源碼:https://codepen.io/shadeed/pen/dc4e82f3c873cc64ae5c5bc4a3f4ef9f?editors=0100
你知道大多數網站使用的頂部邊框嗎?通常,它的顏色與品牌顏色相同,這會賦予一些個性。
我們支持邊框的初始值為3px。如何將固定值轉換為視口對象?下面是如何計算它的等效的vw。
vw = (Pixel Value / Viewport width) * 100
視口寬度用于估計像素值與所需vw單位之間的比率。
對于我們的示例,我們為 header 添加以下樣式:
.header {
border-top: 4px solid #8f7ebc;
}
在我的情況下,視口寬度為1440(這不是固定數字,請用你自己的數字替換)
vw = (4 / 1440) * 100 = 0.277
.header {
border-top: 0.277vw solid #8f7ebc;
}
更好的是,我們可以使用一個基本像素值,而視口單元可以是一個附加的。
.header {
border-top: calc(2px + 0.138vw) solid $color-main;
}
移動設備中存在一個常見問題,即使使用100vh,也會滾動,原因是地址欄的高度可見。Louis Hoebregts 寫了一篇關于這個問題的文章,并給出了一個簡單的解決方案。
.my-element {
height: 100vh; /* 不支持自定義屬性的瀏覽器的回退 */
height: calc(var(--vh, 1vh) * 100);
}
// 首先,我們得到視口高度,我們乘以 1% 得到一個vh單位的值
let vh = window.innerHeight * 0.01;
// 然后,將`--vh`自定義屬性中的值設置為文檔的根目錄一個屬性
document.documentElement.style.setProperty('--vh', `${vh}px`);
事例源碼:https://codepen.io/shadeed/pen/1d18ca2d23ec0038c759dc62dc3fd8c3?editors=0110
作者:Ahmad shaded 譯者:前端小智 來源:sitepoint
原文:https://ishadeed.com/viewport-units/
*請認真填寫需求信息,我們會在24小時內與您取得聯系。