分析 CSS 视口单位 dvh、lvh、svh 的适配机制

CSS 视口单位 dvh、lvh、svh 的适配机制

大家好,今天我们来深入探讨一下 CSS 中的视口单位 dvhlvhsvh。这些单位是响应式 Web 设计中比较新的成员,旨在解决移动设备上动态变化的视口高度问题,例如地址栏的出现和消失,以及不同设备上的差异。我们将深入理解它们的工作原理,探讨它们之间的差异,并学习如何在实际项目中有效地利用它们。

视口单位的演进:传统视口单位的局限性

dvhlvhsvh 出现之前,我们常用的视口单位是 vwvhvw 代表视口宽度的 1%,vh 代表视口高度的 1%。然而,在移动设备上,vh 的表现并不总是如我们所愿。当移动浏览器的地址栏出现或消失时,视口的高度会发生变化,导致使用 vh 单位的元素的高度也会随之变化,从而可能引起布局抖动和用户体验问题。

例如,考虑以下 CSS 代码:

.full-height {
  height: 100vh;
  width: 100%;
  background-color: lightblue;
}

如果我们在一个移动设备上应用这段 CSS,当地址栏显示时,.full-height 元素的高度会占据整个屏幕,包括地址栏。但当地址栏消失时,.full-height 元素的高度会增加,超出屏幕的可见范围,导致页面出现滚动条。这显然不是我们想要的效果。

为了解决这个问题,CSS 工作组引入了 dvhlvhsvh 这三个新的视口单位。

dvh:动态视口高度

dvh (Dynamic Viewport Height) 代表动态视口高度的 1%。动态视口高度是指在地址栏出现和消失时,视口实际可用的高度。dvh 会随着地址栏的状态变化而动态调整,以确保元素的高度始终与当前可见的视口高度相匹配。

换句话说,100dvh 始终等于当前视口实际的高度,无论地址栏是否显示。

修改之前的 CSS 代码,使用 dvh 代替 vh

.full-height {
  height: 100dvh;
  width: 100%;
  background-color: lightblue;
}

现在,无论地址栏是否显示,.full-height 元素的高度都会始终占据整个可见的视口高度,而不会导致页面出现不必要的滚动条。

dvh 的优势:

  • 避免布局抖动: 由于 dvh 会动态调整,因此可以避免因地址栏状态变化而引起的布局抖动。
  • 始终占据整个可见视口: 100dvh 始终等于当前可见的视口高度,确保元素始终占据整个屏幕。

dvh 的劣势:

  • 动态变化: dvh 的值会随着地址栏的状态变化而动态变化,这可能会导致一些意外的布局问题,特别是在复杂的布局中。
  • 兼容性: dvh 是一个相对较新的单位,在一些旧版本的浏览器中可能不被支持。

lvh:最大视口高度

lvh (Large Viewport Height) 代表最大视口高度的 1%。最大视口高度是指视口在扩展到最大尺寸时的尺寸。 这意味着当地址栏缩回时, lvh 就会使用此时的视口高度。

换句话说,100lvh 等于视口在最大扩展时的视口高度,即使当前地址栏可见,导致实际视口高度较小。它代表了理论上视口可以达到的最大高度。

.full-height {
  height: 100lvh;
  width: 100%;
  background-color: lightblue;
}

使用 lvh 后,元素的高度将基于地址栏隐藏时的视口高度。如果地址栏显示,元素可能会超出当前可见的视口范围。

lvh 的优势:

  • 固定高度: lvh 的值是固定的,不会随着地址栏的状态变化而变化。
  • 最大高度: lvh 代表视口可能达到的最大高度,可以用于创建在最大视口高度下看起来最佳的布局。

lvh 的劣势:

  • 可能超出视口: 如果地址栏显示,使用 lvh 的元素可能会超出当前可见的视口范围。
  • 不适用于动态布局: 由于 lvh 的值是固定的,因此不适用于需要根据当前视口高度动态调整的布局。

svh:最小视口高度

svh (Small Viewport Height) 代表最小视口高度的 1%。最小视口高度是指视口在收缩到最小尺寸时的尺寸。 这意味着当地址栏显示时, svh 就会使用此时的视口高度。

换句话说,100svh 等于视口在最小收缩时的视口高度,即使当前地址栏隐藏,导致实际视口高度较大。它代表了理论上视口可能达到的最小高度。

.full-height {
  height: 100svh;
  width: 100%;
  background-color: lightblue;
}

使用 svh 后,元素的高度将基于地址栏显示时的视口高度。如果地址栏隐藏,元素的高度可能会小于当前可见的视口高度。

svh 的优势:

  • 固定高度: svh 的值是固定的,不会随着地址栏的状态变化而变化。
  • 最小高度: svh 代表视口可能达到的最小高度,可以用于创建在最小视口高度下看起来最佳的布局。

svh 的劣势:

  • 可能小于视口: 如果地址栏隐藏,使用 svh 的元素的高度可能会小于当前可见的视口高度,导致页面出现空白。
  • 不适用于动态布局: 由于 svh 的值是固定的,因此不适用于需要根据当前视口高度动态调整的布局。

dvh、lvh 和 svh 的比较

为了更清晰地了解 dvhlvhsvh 之间的差异,我们可以将它们进行比较:

特性 dvh (动态视口高度) lvh (最大视口高度) svh (最小视口高度)
动态变化,随地址栏状态变化而调整 固定值,等于最大视口高度 固定值,等于最小视口高度
地址栏显示时 占据当前可见的视口高度 可能超出当前可见的视口范围 占据当前可见的视口高度
地址栏隐藏时 占据当前可见的视口高度 占据当前可见的视口高度 可能小于当前可见的视口高度
适用场景 需要根据当前视口高度动态调整的布局,避免布局抖动 需要在最大视口高度下看起来最佳的布局 需要在最小视口高度下看起来最佳的布局
兼容性 相对较新,在一些旧版本的浏览器中可能不被支持 相对较新,在一些旧版本的浏览器中可能不被支持 相对较新,在一些旧版本的浏览器中可能不被支持

在实际项目中应用 dvh、lvh 和 svh

了解了 dvhlvhsvh 的工作原理后,我们就可以在实际项目中应用它们了。

1. 使用 dvh 创建全屏布局:

<!DOCTYPE html>
<html>
<head>
  <title>Full Screen Layout</title>
  <style>
    body {
      margin: 0;
      overflow: hidden; /* 阻止滚动条 */
    }

    .full-screen {
      width: 100%;
      height: 100dvh; /* 使用 dvh 确保占据整个视口高度 */
      background-color: #f0f0f0;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 2em;
    }
  </style>
</head>
<body>
  <div class="full-screen">
    全屏内容
  </div>
</body>
</html>

在这个例子中,我们使用 100dvh 来设置 .full-screen 元素的高度,确保它始终占据整个可见的视口高度,无论地址栏是否显示。

2. 使用 lvh 创建在最大视口高度下看起来最佳的布局:

<!DOCTYPE html>
<html>
<head>
  <title>Large Viewport Layout</title>
  <style>
    body {
      margin: 0;
    }

    .header {
      width: 100%;
      height: 20lvh; /* 头部高度占据最大视口高度的 20% */
      background-color: #333;
      color: white;
      text-align: center;
      line-height: 20lvh;
    }

    .content {
      width: 100%;
      height: 80lvh; /* 内容区域占据最大视口高度的 80% */
      background-color: #eee;
      padding: 20px;
    }
  </style>
</head>
<body>
  <div class="header">
    头部
  </div>
  <div class="content">
    内容区域
  </div>
</body>
</html>

在这个例子中,我们使用 lvh 来设置头部和内容区域的高度,确保它们在最大视口高度下看起来最佳。即使地址栏显示,头部和内容区域的高度仍然会基于最大视口高度计算,可能会超出当前可见的视口范围。

3. 使用 svh 创建在最小视口高度下看起来最佳的布局:

<!DOCTYPE html>
<html>
<head>
  <title>Small Viewport Layout</title>
  <style>
    body {
      margin: 0;
    }

    .footer {
      width: 100%;
      height: 10svh; /* 底部高度占据最小视口高度的 10% */
      background-color: #333;
      color: white;
      text-align: center;
      line-height: 10svh;
      position: fixed;
      bottom: 0;
    }

    .content {
      width: 100%;
      min-height: 90svh; /* 内容区域最小高度占据最小视口高度的 90% */
      background-color: #eee;
      padding: 20px;
    }
  </style>
</head>
<body>
  <div class="content">
    内容区域
  </div>
  <div class="footer">
    底部
  </div>
</body>
</html>

在这个例子中,我们使用 svh 来设置底部的高度和内容区域的最小高度,确保它们在最小视口高度下看起来最佳。即使地址栏隐藏,底部的高度和内容区域的最小高度仍然会基于最小视口高度计算,内容区域的高度可能会小于当前可见的视口高度,导致页面出现空白。

4. 结合媒体查询使用:

为了兼容不支持 dvhlvhsvh 的旧版本浏览器,我们可以结合媒体查询来使用这些单位。

.element {
  height: 100vh; /* Fallback for older browsers */
  height: 100dvh; /* Use dvh when supported */
}

@supports (height: 100dvh) {
  .element {
    height: 100dvh;
  }
}

在这个例子中,我们首先使用 vh 作为回退方案,然后使用 @supports 媒体查询来检测浏览器是否支持 dvh。如果支持,则使用 dvh 代替 vh

5. 使用 JavaScript 辅助:

在某些情况下,我们可能需要使用 JavaScript 来辅助计算视口高度,并将其设置为 CSS 变量,然后在 CSS 中使用这些变量。

function setViewportVariables() {
  let vh = window.innerHeight * 0.01;
  document.documentElement.style.setProperty('--vh', `${vh}px`);

  let lvh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0, screen.availHeight || 0) * 0.01;
  document.documentElement.style.setProperty('--lvh', `${lvh}px`);

  let svh = Math.min(document.documentElement.clientHeight || 0, window.innerHeight || 0, screen.availHeight || 0) * 0.01;
  document.documentElement.style.setProperty('--svh', `${svh}px`);
}

// Set the variables initially
setViewportVariables();

// Update the variables when the window is resized
window.addEventListener('resize', setViewportVariables);
.element {
  height: calc(var(--vh, 1vh) * 100); /* Use CSS variable for height */
}

.large-element {
  height: calc(var(--lvh, 1vh) * 100);
}

.small-element {
  height: calc(var(--svh, 1vh) * 100);
}

在这个例子中,我们使用 JavaScript 来计算视口高度,并将其设置为 CSS 变量 --vh--lvh--svh。然后在 CSS 中使用 calc() 函数和 var() 函数来使用这些变量。

总结:选择合适的视口单位

dvhlvhsvh 都是非常有用的视口单位,可以帮助我们更好地处理移动设备上的动态视口高度问题。选择哪个单位取决于具体的应用场景和需求。

  • 如果需要创建始终占据整个可见视口高度的布局,并且需要避免布局抖动,那么 dvh 是一个不错的选择。
  • 如果需要在最大视口高度下看起来最佳的布局,并且可以接受在地址栏显示时元素超出当前可见的视口范围,那么 lvh 是一个不错的选择。
  • 如果需要在最小视口高度下看起来最佳的布局,并且可以接受在地址栏隐藏时元素的高度小于当前可见的视口高度,那么 svh 是一个不错的选择。

希望今天的讲解能够帮助大家更好地理解和应用 dvhlvhsvh。谢谢大家!

兼容性考量及优化

在使用这些新的视口单位时,一定要注意兼容性问题。可以使用 caniuse.com 等网站查询浏览器的支持情况。为了确保在不支持这些单位的浏览器中也能正常显示,可以采取以下措施:

  • 提供回退方案: 使用传统的 vh 单位作为回退,并通过 @supports 查询来使用新的视口单位。
  • 使用 JavaScript 辅助: 使用 JavaScript 检测浏览器是否支持新的视口单位,如果不支持,则使用 JavaScript 计算视口高度并将其设置为元素的样式。
  • 渐进增强: 将新的视口单位作为渐进增强的一部分,确保即使在不支持这些单位的浏览器中,页面也能正常显示,只是可能无法达到最佳的视觉效果。

未来发展方向

随着 Web 技术的不断发展,我们可以期待更多的 CSS 新特性出现,以解决响应式 Web 设计中遇到的各种挑战。例如,未来可能会出现更智能的视口单位,能够自动适应不同设备和场景下的视口高度,从而简化我们的开发工作。同时,我们也需要不断学习和掌握新的技术,才能更好地应对 Web 开发的未来。

灵活运用,提升用户体验

理解 dvhlvhsvh 的特性,并结合实际场景灵活运用,可以帮助我们更好地处理移动设备上的视口高度问题,从而提升用户体验。在开发过程中,要充分考虑不同设备的差异,并采取合适的策略来确保页面在各种设备上都能正常显示。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注