前言
当我们想要将一个元素高度设置为全屏(整个视窗)高度时,经常使用以下代码:
.element {
height: 100vh;
}
以上在 PC 上没有任何问题,问题主要出现在移动端。由于移动端屏幕尺寸小,寸土寸金,有些厂商(如 iOS Safari)会有特殊的处理(或者说是 bug)。Safari 上只在必要时才显示工具栏,尽可能给网站更多的空间,这就是为什么在滚动时工具栏会自动隐藏。这导致了处理视窗高度时出现问题:
- 每次工具栏隐藏和显示时视窗高度会改变;
- 工具栏会遮挡视窗的一部分。
问题说明
例如一个常规的网站布局,header 固定在顶部(sticky 或者 fixed 均可)。左侧是导航目录,高度为 视窗高度 - header 高度
。右侧为内容区。如果我们将左侧导航目录高度设置为 100vh - header 高度
,就会出现工具栏遮挡导航目录的问题,滚动条滚动到底部了,仍有一部分内容被工具栏遮挡。
如何解决这个问题呢?比较简单的就是使用 JavaScript 动态获取视窗高度。视窗高度变化时,更新导航目录高度。
解决方案
处理思路如下:
- 页面加载后,获取视窗高度,更新导航目录高度;
- 监听窗口 resize 事件,触发时,重新更新导航目录高度。
为了方便更新导航目录高度,我们使用 css 变量。
// 定义一个视窗高度变量
:root {
--i-window-height: 100vh;
}
// 设置导航目录高度,header 高度为 4rem
.sidebar {
height: calc(var(--i-window-height) - 4rem);
}
接下来只需要更新 --i-window-height
就可以了。
在 Vue3 中实现代码如下:
<script setup>
import { onBeforeUnmount, onMounted } from "vue";
function updateWindowHeight() {
let windowHeight = window.innerHeight;
let html = document.querySelector(":root");
if (windowHeight > 0 && html) {
html.style.setProperty("--i-window-height", `${windowHeight}px`);
}
}
onMounted(() => {
updateWindowHeight();
on(window, "resize", updateWindowHeight);
});
onBeforeUnmount(() => {
off(window, "resize", updateWindowHeight);
});
</script>
参考资料: