Ios 的 100vh 问题解决方案

让我们先复现一下问题。 准备一个支持 PWA 的移动端网站。为方便演示,我们编写了一个简单的网页:

<html>
  <head>
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1,viewport-fit=cover"
    />
    <meta name="theme-color" content="#fff" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-touch-fullscreen" content="yes" />
    <meta
      name="apple-mobile-web-app-status-bar-style"
      content="black-translucent"
    />
  </head>

  <!-- body 深灰色  -->
  <body style="background: #9D9D9D">
    <!-- div 天蓝色 -->
    <div style="height: 100%; background: #007AFF" />
  </body>
</html>

我们也为网站添加一份manifest.json,从而允许网站添加到桌面。我们之后将添加到桌面的网页称之为WebApp

{
  // ...其他属性
  display: "fullscreen",
}

如果将htmlbody均设置为100%高度,在 safari 中不会出现问题,但是 WebApp 会发现div无法占满全屏,底部缺失了env(safe-area-inset-bottom)高度。

<html style="height: 100%">
  <head>
    <!-- 省略 -->
  </head>

  <body style="height: 100%; background: #9D9D9D">
    <div style="height: 100%; background: #007AFF" />
  </body>
</html>

Body 100%

如果将body设置为100vh高度,在 WebApp 中不会存在问题,但是在 safari 中会出现滚动条。

<html>
  <head>
    <!-- 省略 -->
  </head>

  <body style="height: 100vh; background: #9D9D9D">
    <div style="height: 100%; background: #007AFF" />
  </body>
</html>

Body 100vh

解决方案

webkit-fill-available

我最开始也查找了不少资料,主要的解决方案使用过-webkit-fill-available自动填满剩余高度来解决。

@supports (-webkit-touch-callout: none) {
  body {
    height: -webkit-fill-available`;
  }
}

这个方案也是postcss-100vh-fix插件的解决方案。

如果我们不是将apple-mobile-web-app-status-bar-style设置为black-translucent,在manifest.json中添加了"display": "fullscreen"并且我们还有一个有刘海的苹果手机。那么一切都将像我们预期一样。

然而我手上恰好有一个刘海屏的苹果手机。

另一种解决方案

其实当我们发现,在 safari 中100%能够正常运行,在 WebApp 中100vh能够正常运行时。我们其实已经找到了一个新的解决方案:

  1. 判断当前运行环境是 WebApp 还是 Safari。
  2. 当运行环境是 WebApp 时,设置100vh
  3. 当运行环境是 Safari 时,设置100%
// https://val-istar-guo.com/script/fix-100vh.js
if (document) {
  // window.navigator.standalone 判断是否是ios的WebApp
  if (window.navigator.standalone) {
    // WebApp下需要设定100vh才能获取到正确的高度
    const styles = `html, body { height: 100vh; }`;
    const styleSheet = document.createElement("style");
    styleSheet.innerText = styles;
    document.head.appendChild(styleSheet);
  } else {
    // 非WebApp下需要设定100%才能获取到正确的高度
    // 设定100vh在ios下会导致页面出现滚动条
    const styles = `html, body { height: 100%; }`;
    const styleSheet = document.createElement("style");
    styleSheet.innerText = styles;
    document.head.appendChild(styleSheet);
  }
}

我们将这个文件加入 html 文件的 head 中:

<html>
  <head>
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1,viewport-fit=cover"
    />
    <meta name="theme-color" content="#fff" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-touch-fullscreen" content="yes" />
    <meta
      name="apple-mobile-web-app-status-bar-style"
      content="black-translucent"
    />

    <!-- 在浏览器渲染前添加修复100vh问题的css -->
    <script src="https://val-istar-guo.com/script/fix-100vh.js"></script>
  </head>

  <body style="background: #9D9D9D">
    <div style="height: 100%; background: #007AFF" />
  </body>
</html>

这样,我们就彻底解决了 ios 系统的 100vh 问题。

如果需要min-height,可以直接修改fix-100vh.js脚本。

加我微信,成为我的朋友wechat
Copyright © 2018 val-istar-guo.com All rights reserved苏ICP备2023015265号