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", }
如果将html
、body
均设置为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
设置为100vh
高度,在 WebApp 中不会存在问题,但是在 safari 中会出现滚动条。
<html> <head> <!-- 省略 --> </head> <body style="height: 100vh; background: #9D9D9D"> <div style="height: 100%; background: #007AFF" /> </body> </html>
解决方案
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
能够正常运行时。我们其实已经找到了一个新的解决方案:
- 判断当前运行环境是 WebApp 还是 Safari。
- 当运行环境是 WebApp 时,设置
100vh
。 - 当运行环境是 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
脚本。