CSS Viewport单位

例如,当需要根据视口大小调整元素的大小时。视口单位为 vw、vh、vmin 和 vmax。
考虑下图:
新Viewport单位 - 图1
值 50vw 的意思是:给元素一个等于视口宽度 50% 的宽度。

问题

当使用 100vh 调整元素大小以占据移动端视口的全部高度时,它将大于顶部和底部栏之间的空间。这种情况会发生在滚动时缩小 UI 的浏览器中,例如 Android 上的 Safari 或 Chrome。
下图显示了每个移动浏览器的顶部和底部UI是如何不同的。
新Viewport单位 - 图2
新Viewport单位 - 图3
假设有一个充满整个屏幕的加载视图。

  1. /* 可以使用bottom: 0代替height: 100vh,但这里是故意突出这个问题。 */
  2. .loading-wrapper {
  3. position: fixed;
  4. left: 0;
  5. right: 0;
  6. top: 0;
  7. height: 100vh;
  8. display: grid;
  9. place-items: center;
  10. }

考虑下图:
新Viewport单位 - 图4
加载图标在 CSS 中居中,但从视觉上看,它看起来稍微位于底部。为什么会发生这种情况?
新Viewport单位 - 图5
对于浏览器来说,height: 100vh 意味着元素将填充视口高度,但它不会动态的计算值。这意味着底部地址栏和工具栏不会被计算。
因此,期望 100vh 等于从视口顶部到地址栏 UI 顶部。
新Viewport单位 - 图6
当向下滚动时,地址栏 UI 将缩小其尺寸。这很好,因为它为用户提供了更多的垂直空间来浏览页面。与此同时,它也在某种程度上破坏了 UI。
在下图中,当地址栏可见时,垂直空间的中心不符合预期。滚动时,看起来不错。
新Viewport单位 - 图7
注意是如何突出显示不可见区域的。当向下滚动时,它变得可见。如何在CSS中处理这个问题?

小、大和动态视口单位

为了解决这个问题,CSS 工作组同意采用一组新的单位:svh、lvh 和 dvh。它们分别代表小视口、大视口和动态视口。
新Viewport单位 - 图8

小视口

svh 表示地址栏 UI 尚未缩小尺寸时的视口高度。
新Viewport单位 - 图9

大视口

lvh 表示地址栏 UI 缩小尺寸后的视口高度。
新Viewport单位 - 图10

动态视口

从名字上看,这个单位是动态的。这意味着它将根据地址栏 UI 是否缩小而使用小的、中间的和大的单位。
新Viewport单位 - 图11
在初始滚动期间,动态视口单位将随着浏览器 UI 的收缩而改变。这是一个展示动态视口变化的视频:
新Viewport单位 - 图12

用例和示例

具有粘性页眉和页脚的弹窗

新Viewport单位 - 图13
在这个例子中,有一个带有粘性页眉和页脚的弹窗。如果内容足够长,中间部分应该滚动。
考虑以下 CSS:

  1. .modal {
  2. position: fixed;
  3. top: 0;
  4. left: 0;
  5. right: 0;
  6. height: 100vh;
  7. }

使用 100vh 将使弹窗的底部部分不可见。在示例中,这意味着页脚将不可见,这将破坏用户体验。
以下是 iOS 上传统和新视口单位的表现:
新Viewport单位 - 图14
..加上 Android 上的 Chrome 和 Firefox:
新Viewport单位 - 图15
为了解决这个问题,可以使用 svh 或 dvh 单位。
这是一个视频,显示了 dvh 和 vh 之间的差异。
新Viewport单位 - 图16

主页横幅

新Viewport单位 - 图17
这是一种常见的情况,需要使主页横幅的高度等于整个视口高度减去标题高度。在这种情况下,使用传统的 vh 在 iOS Safari、Firefox 和 Android 版 Chrome 等会在滚动时缩小 UI 的浏览器中会失败。
首先,需要确保标题高度是固定的。为此使用了 min-height。

  1. :root {
  2. --header-height: 60px;
  3. }
  4. .site-header {
  5. position: sticky;
  6. top: 0;
  7. min-height: var(--header-height, initial);
  8. }

之后,将 min-height 添加到主页横幅并使用 calc()

  1. .hero {
  2. min-height: calc(100svh - var(--header-height));
  3. }

使用 vh 时,装饰元素(紫色)根本不可见。事实上,如果仔细观察,会发现它模糊的显示在 iOS Safari 中的地址栏 UI 下方,而在 Android 浏览器中则被裁剪掉了。
以下是 Safari iOS 上 svh 和 vh 的比较。
新Viewport单位 - 图18
..加上 Android 上的 Chrome 和 Firefox:
新Viewport单位 - 图19
请观看以下视频并找出使用 svh 和 vh 之间的区别。
新Viewport单位 - 图20
在这种情况下,使用svh就可以解决问题。

是否可以将 Dvh 设置为默认单位?

起初,答案是“是的,为什么不呢?”。然后我想,dvh 值会随着滚动而改变,所以当它用于诸如 font-size 之类的东西时,可能会产生一种令人困惑的体验。

  1. h1 {
  2. font-size: calc(1rem + 5dvh);
  3. }

新Viewport单位 - 图21
观看以下视频,注意地址栏 UI 缩小后字体大小如何变化:
新Viewport单位 - 图22

小心使用 Dvh 视口单位

动态视口单位可能会影响页面的性能,因为浏览器需要花费大量工作来重新计算用户向上或向下滚动的样式。
我没有机会进行密集的性能测试,但使用时我会小心。我希望我能有时间在这里更新这一点。

新视口单位有用的其他地方

这些新的视口单位可能不仅仅适用于移动浏览器。事实上,现在可以在电视上浏览网页。谁知道电视上会出现哪种浏览器,其 UI 会在滚动时发生变化,从而调整视口的大小?
例如,以下是在 Android TV 上查看的主页横幅示例:
新Viewport单位 - 图23
效果很好,即是动态 UI 也能继续生效。