移动端 100vh 遇到的问题及解决方案

老牛浏览 1458评论 0发表于

前言

当我们想要将一个元素高度设置为全屏(整个视窗)高度时,经常使用以下代码:

css
.element {
    height: 100vh;
}

以上在 PC 上没有任何问题,问题主要出现在移动端。由于移动端屏幕尺寸小,寸土寸金,有些厂商(如 iOS Safari)会有特殊的处理(或者说是 bug)。Safari 上只在必要时才显示工具栏,尽可能给网站更多的空间,这就是为什么在滚动时工具栏会自动隐藏。这导致了处理视窗高度时出现问题:

  • 每次工具栏隐藏和显示时视窗高度会改变;

  • 工具栏会遮挡视窗的一部分。

问题说明

df6d4f88-7405-458d-9345-cc5bc090a516

例如一个常规的网站布局,header 固定在顶部(sticky 或者 fixed 均可)。左侧是导航目录,高度为 视窗高度 - header 高度。右侧为内容区。如果我们将左侧导航目录高度设置为 100vh - header 高度,就会出现工具栏遮挡导航目录的问题,滚动条滚动到底部了,仍有一部分内容被工具栏遮挡。

如何解决这个问题呢?比较简单的就是使用 JavaScript 动态获取视窗高度。视窗高度变化时,更新导航目录高度。

解决方案

处理思路如下:

  1. 页面加载后,获取视窗高度,更新导航目录高度;

  2. 监听窗口 resize 事件,触发时,重新更新导航目录高度。

为了方便更新导航目录高度,我们使用 css 变量。

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>

参考资料:

点赞
收藏
暂无评论,快来发表评论吧~
私信
老牛@ilaoniu
老牛,俗称哞哞。单纯的九零后理工小青年。喜欢折腾,爱玩,爱音乐,爱游戏,爱电影,爱旅游...
最后活跃于