vh 存在問題?試試動態視口單位之 dvh、svh、lvh

2023-01-31 12:00:39

大部分同學都知道,在 CSS 世界中,有 vw、vh、vmax、vmin 這幾個與視口 Viewport 相關的單位。

正常而言:

  1. 1vw 等於1/100的視口寬度 (Viewport Width)
  2. 1vh 等於1/100的視口高度 (Viewport Height)
  3. vmin — vmin 的值是當前 vw 和 vh 中較小的值
  4. vmax — vw 和 vh 中較大的值

vh 在行動端存在重大問題!

但是,在行動端,情況就不太一樣了。100vh 不總是等於一螢幕的高度。有的時候,100vh 高度會出現卷軸。

可以使用行動端 Chrome 瀏覽器掃描下面的二維條碼檢視實際 100vh 在行動端的表現:

根因在於:

  1. 很多瀏覽器,在計算 100vh 的高度的時候,會把位址列等相關控制元件的高度計算在內2
  2. 同時,很多時候,由於會彈出軟鍵盤等操作,在彈出的過程中,100vh 的計算值並不會實時發生變化!

這也就變相導致了許多基於 100vh 想實現的效果無形中會產生很多問題。

圖片來源於:The large, small, and dynamic viewport units

新視口相關單位之 lvh、svh、dvh

為了解決上述的問題,規範新推出了三類單位,分別是:

  1. The large viewport units(大視口單位):lvw,lvh, lvi, lvb, lvmin, and lvmax
  2. The small viewport units(小視口單位):svw, svh, svi, svb, svmin, and svmax
  3. The dynamic viewport units(動態視口單位):dvw, dvh, dvi, dvb, dvmin, and dvmax

別看看上去很多,其實很好記憶,vw/vw/vmax/vmin 的字首是 v,而:

  1. 大視口單位的字首是 lv,意為 large viewport
  2. 小視口單位的字首是 sv,意為 small viewport
  3. 動態視口單位的字首是 dv,意為 dynamic viewport

這裡我們著重關注 lvhsvhdvh。它們三者與 vw 有什麼異同呢?

先來看大視口與小視口,規範對它們的定義是:

  1. Large Viewport: The viewport sized assuming any UA interfaces that are dynamically expanded and retracted to be retracted.
  2. Small Viewport: The viewport sized assuming any UA interfaces that are dynamically expanded and retracted to be expanded.

翻譯一下:

  1. 大視口(Large Viewport):視口大小假設任何動態擴充套件和縮回的 UA 介面都沒有展開
  2. 小視口(Small Viewport):視口大小假設任何動態擴充套件和縮回的 UA 介面都展開了

因此,對應到高度之上,其狀態大致如下:

理解了大視口與小視口之後,再理解動態視口就輕鬆了些。

簡單而言,動態視口的意思是:

  1. 動態工具列展開時,動態視口等於小視口的大小
  2. 當動態工具列被縮回時,動態視口等於大視口的大小

因此,也就能得到下面這張圖:

其中,dvhdvwdvmaxdvmin 對標 vhvwvmaxvmin 比較好理解。

剩下,dvidvb 解釋一下。其實,在之前也有 vivb 兩個單位:

  1. vi:vi 代表 Viewport Inline,代表檔案的內聯方向。在水平書寫方向上,這對應於視口的寬度,而在垂直書寫方向上,這表示視口的高度。記住 inline 方向的簡單方法是記住它與文字的方向相同。
  2. vb:vb 代表 Viewport block,代表檔案的塊方向。這與 vi 水平書寫方向相反,這將對應於視口高度,而在垂直檔案中,這將表示視口的寬度。

因此,vi 和 vb 屬於兩個邏輯單位。關於 CSS 中的方位與順序,邏輯單位相關的內容,你可以看看我的這篇文章:https://github.com/chokcoco/iCSS/issues/127

理解了 vivbdvidvb 也就很好理解了,它們分別表示動態視口下的 Viewport Inline 與 Viewport block。同理去理解大視口、小視口下的 lvilvbdvidvb

dvh、svh、lvh 它們的相容性(2023-01-25)

截止到書寫本文的時間,它們已經被 Chrome 108+ 支援,而 firefox、Safari 在更早的階段,就已經開始支援這些新單位了。

看看 CanIUse:

因此,在不久的將來,全面使用 dvh 替代 vh,能有效的減少非常多因為 vh 在行動端的表現而引起的問題

總結一下

簡單再總結一下,本文通過 vh 在移動存在的問題入手,引出了規範新增的三大類新的和視口相關的單位。分別是:

  1. 大視口(Large Viewport)
  2. 小視口(Small Viewport)
  3. 動態視口(dynamic viewport)

它們的出現,極大的彌補了之前 vh/vw 等視口單位存在的問題。CSS 的更新迭代一直在快速持續,很多內容還是有必要不斷了解學習,在不久的將來就能很快應用在業務中。

此外,除了動態視口外,其實 CSS 還更新了與容器大小相關的相對單位 -- 譬如 cqwcqh

  • cqw:表示容器查詢寬度(Container Query Width)佔比。1cqw 等於容器寬度的 1%。假設容器寬度是 1000px,則此時1cqw 對應的計算值就是 10px
  • cqh: 表示容器查詢高度(Container Query Height)佔比。1cqh 等於容器高度的 1%

容器查詢:它給予了 CSS,在不改變瀏覽器視口寬度的前提下,只是根據容器的寬度變化,對佈局做成調整的能力。

也就是說,CSS 除了在視口這條路之外,也逐漸在擴充探索以及完善與容器大小變化相關的能力。

假期在群裡看到了這樣一張很有意思的圖:

可以預見,未來 CSS 將朝著越來越複雜、功能越來越強大繼續發展,諸多新特性層出不窮。可能不再是很多人之前眼中的比較簡單的一門語言。

不知是好是壞,且學且珍惜吧。

最後

文中關於動態視口相關的問題,部分圖片來自這篇文章 -- The large, small, and dynamic viewport units,可以一起學習,加深印象。

好了,本文到此結束,希望本文對你有所幫助