vh 全拼 viewport height,是 CSS 中的长度单位,意为将可视区域分为 100 份,每一份即为 1vh。
我们通常习惯使用 height: 100vh; 来设定一个一屏高度的容器。然而这个特性在 IOS 移动端存在一些问题。

可以看到在 Safari 中 100vh 还包括底部的 bar,这会导致一系列问题比如图中的底部按钮被遮挡。
在 IOS15 中地址栏被合并到了底部的 bar 上使得这种情况变得更加糟糕:

要解决这个问题我们只需要判断出是否为 IOS 设备并且特殊处理即可。
这个逻辑交给 JavaScript 非常简单,但为了「优雅」与「性能」我们选择用 CSS 解决,因此我们需要接触一些不常用的 CSS 属性
@supports
中文名为特性查询。其本身用来判定某个 CSS 表达式是否有效(有效可以指是否能被浏览器解析)

有意思的是,它还支持和 selector、not、and、or 操作法联用。它常用于判断某个 CSS 属性是否有效,当「某个CSS属性」为某个浏览器特有时我们就可以利用它来确实浏览器环境。
-webkit-touch-callout
用于禁用默认的 callout 展示,callout 是指当触摸并按住一个元素时出现的提示。这个属性只在 Safari 中被支持。
-webkit-fill-available
这是一个兼容性非常烂的属性,作用为撑满块级元素包括宽、高。它的本体描述为 stretch,能够比 100vh 更准确的描述 viewport 高度。

万幸的是我们的目标浏览器 Safari 支持它!
核心代码
由于我们的项目中使用了 tailwindcss,所以可以为已有的 className 增加样式。(其他情况也同理,全局命名一个公用的 clssName 使用起来会非常方便)
@supports (-webkit-touch-callout: none) {
.h-screen {
height: -webkit-fill-available;
}
}
这样 100vh 在 IOS Safari 的兼容性就解决了。
原理参考来自于 postcss-100vh-fix。
所以如果项目中使用了 postcss 处理 CSS 则可以使用这个插件轻松解决问题。需要注意的是 css-in-js 的组件以及 tailwindcss 并不能被 postcss 覆盖到。