David Chanin 写了一篇简短的文章,总结了在移动浏览器中将元素的height
设置为100vh
并在其底部定位某个元素时出现的问题。
以下图形对此进行了总结

问题在于 Chrome 在显示地址栏(浏览器 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;
}
您会期望图形中的按钮可见(假设此元素位于页面顶部且您尚未滚动),因为它位于 100vh 元素的底部边缘。但实际上,它隐藏在移动浏览器(包括 iOS Safari 或 Android Chrome)的浏览器 chrome 后面。
我经常使用它
body {
height: 100vh; /* Nice to not have to think about the HTML element parent */
margin: 0;
}
这只是确保主体高度充满整个视窗而不涉及任何其他元素的一种快捷方法。我通常在一些风险较低的演示类型的项目中这样做,但据说即使这样也有点问题,因为您可能会遇到浏览器 chrome 出现和消失时的跳跃现象,或者事物可能不会像您期望的那样居中。
您可能会认为可以使用body { height: 100% }
,但这里也存在一个陷阱。主体是<html>
的子元素,而<html>
的高度仅与其包含的内容一样高,就像任何其他元素一样。
如果您需要主体高度充满整个视窗,您也必须处理 HTML 元素
html, body {
height: 100%;
}
……这并不是什么大问题,并且具有可靠的跨浏览器一致性。
真正棘手的是在底部边缘定位元素。由于在“充满高度”(通常比可见高度高)的容器中使用了position: absolute;
,因此会产生问题。
如果您尝试在屏幕底部放置一个固定导航栏,您可能会使用position: fixed; bottom: 0;
来完成此操作,这似乎效果很好。浏览器 chrome 会像您期望的那样将其向上和向下推(视频)。
水平视窗单位同样奇怪且存在问题,这是因为另一个浏览器 UI:滚动条。如果浏览器窗口有可见的滚动条,滚动条通常会占用视觉空间,尽管 100vw 的值是在不考虑滚动条的情况下计算的。换句话说,100vw 会导致水平滚动,这可能与您预期的不同。
查看 Pen
用于视窗宽度减去滚动条的 CSS 变量 by Shaw (@shshaw)
在 CodePen 上。
我们最近的 CSS 愿望清单汇总多次提到了更好的视窗单位处理,因此开发人员显然对这些事物的更好解决方案非常感兴趣。不过,我不确定这对 Web 兼容性意味着什么,因为更改其工作方式可能会破坏我们所使用(并且肯定仍然存在于野外)的所有解决方法。
在上面的示例中,我想添加 calc() 减去地址栏的高度 :D
height: calc(100vh – 80px) /* 80px 或调整它直到它适合 ;) */
我使用相同的代码,它在生产网站上运行良好!
我最近使用过类似的东西
来解决 iOS Safari 中的相同问题(我认为)。第二行是属性 CSS 东西。啊。我刚看到现在还有一个
-moz-available
。太棒了!
fill-available
已根据最新的规范更改为stretch
。因此,正确用法是
在使用 autoprefixer 后,它可能会给我们(不确定哪些前缀是正确的)
还有一个 React 包可以解决这个问题 https://npmjs.net.cn/package/react-div-100vh
Chrome 曾经将地址栏考虑在内,但这会导致另一个问题:当地址栏滑出视野时,所有使用 vh 单位的元素都会自动调整大小以匹配新的视窗大小,这会导致页面(滚动位置)跳跃。因此,在 2016 年的某个时候,Chrome 实现了与 IOS Safari 相同的行为。
如果您将 html/body 的高度设置为 100% 但将 body 的 display 设置为 flex 且方向为 column,会怎么样?这将允许您拥有一个具有固定高度的页脚,并且主体将占用所有可用空间。