[译] 你知道关于视口单位的这几件事情吗?

1,685 阅读4分钟

原文链接:Some Things You Oughta Know When Working with Viewport Units,by Chris Coyier

David Chanin 写了一篇 简短的文章 总结了在手机端为元素设置 height: 100vh 带来的一个问题。

可以总结为下图:


我们将 一个元素定位在了  _100vh_ 高的元素的底部。带来的问题是,Chrome 浏览器没有把地址栏考虑在内,导致地址栏显示时,迫使底部元素超出视口之外了。

<div class="full-page-element">
  <button>Button</button>
</div>
.full-page-element {
  height: 100vh;
  position: relative;
}

.full-page-element button {
  position: absolute;
  bottom: 10px;
  left: 10px;
}

假设 .full-page-element 是页面里的第一个元素,页面也没发生滚动。我们期望的是看见这个按钮是在可视区域的底部、沿着 100vh 元素的底部边缘显示的。但是由于地址栏的显示,导致这个元素超出视口之外看不见了,在 iOS Safair 和 Android Chrome 中都能看到这个效果。

我经常会使用下段代码:

body {
  height: 100vh; /* 不用考虑父元素高度,直接设置就能生效 */
  margin: 0;
}

这是一个快速的、在不涉及任何其他元素的情况下,设置 body 为全高(full height)的方式。我通常会在低风险的演示 demo 上这么做,但是这还是有问题的,因为随着浏览器地址栏的出现和消失,页面可能会发生跳动,或者说页面可能不会像我想象中的那样展示。

你可能想到使用 body { height: 100% } 来解决问题,但这也有一个 问题body<html> 的子元素,而 <html> 的高度默认是由内容撑开的。

如果你需要设置 body 为全高,也需要同时设置 <html> 才行:

html, body { 
  height: 100%;
}

……这并不是什么大不了的事情,它具有可靠的跨浏览器一致性。

💡 译注:

这是作者要讲的 第一个问题—— 100vh 没有将手机端的地址栏计算在内,导致地址栏出现时,相对于 100vh 元素定位在底部的元素会因为地址栏的出现,被推出到视口之外。

这个问题的解决办法是改用 html, body {  height: 100%; }  声明解决。

能看出来,底部边缘的定位是很复杂的。再来看看上面 button 元素的定位代码:

.full-page-element button {
  position: absolute;
  bottom: 10px;
  left: 10px;
}

button 元素是 position: absolute 定位的,当因为父元素 .full-page-element 100vh 的设置出现问题时,那么相对于它进行底部定位的按钮自然也会有问题。

如果我们有在屏幕底部定位元素的需求(比如说一个固定导航),大家可能会使用 position: fixed; bottom: 0; 来解决,这看起来 没什么问题,浏览器也会按照我们预期的工作。

GIF.gif

💡 译注:

这是作者要讲的 第二个问题—— 屏幕底部的固定定位,应该使用 position: fixed 来实现,而不是 position: absolute 定位。

水平视口单元同样是怪异、有问题的,Windows 系统里的页面 滚动条 通常会占用可视空间,而 100vw 的计算是没有把滚动条计算在内的。换句话说,100vw 会以一种你意想不到的方式导致水平滚动。

也就是说,视口单位(Viewport Units)并不能反映是的视口尺寸(viewport's size)。

如果页面存在水平滚动条,那么下面的代码就会导致水平滚动:

.wrapper {
  width: 100vw; /* 这样会有问题 */
}

为了排除滚动条带来的影响,减去它的宽度就可以了。

.wrapper {
  width: calc(100vw - var(--scrollbar-width)); /* 这样就没有问题了 */
}

💡 译注:

这是作者要讲的 第三个问题——  Windows 系统中的滚动条是占据空间的,这个会导致 width: 100vw 的设置带来问题,如果还坚持使用此方式的话,不要忘记减去滚动条的宽度。

这个方式的具体讲解,请参考《100vw 下滚动条引发的问题》这篇文章。

(完)