iPhone X底部安全区域适配为什么设置了padding还是被遮挡?
在做Vue项目时,底部导航栏在iPhone X上总被Home Indicator遮挡,虽然设置了padding-bottom: constant(...),但实际显示还是顶到屏幕边缘。
我按教程写了一个适配组件:
<template>
<div class="safe-area" :style="safeAreaStyle">
</div>
</template>
<script>
export default {
data() {
return {
safeAreaStyle: {
paddingBottom: window.safeAreaInsets?.bottom + 'px'
}
}
}
}
</script>
但测试时发现:真机iOS15.2上正常,iOS13.7却报错window.safeAreaInsets is undefined。难道只能用meta viewport标签和CSS变量一起用吗?实在搞不懂怎么兼容了
window.safeAreaInsets根本不靠谱,尤其 iOS 13.7 上连这个属性都不存在,直接报错,这真不是你写错了,是苹果自己在挖坑。血泪教训是:别依赖 JS 去读 safeAreaInsets,尤其别在 data 里直接用它初始化样式,太脆了。
正确姿势是两步走:
第一,CSS 层面用 viewport-fit 和 env()
在 head 里加这行 meta,必须加:
然后在你的底部导航容器里这样写:
注意是
safe-area-inset-bottom(带连字符),不是safeAreaInsets.bottom,这是 CSS 的规范写法,Safari 从 iOS 11.2 就支持了,比 JS 可靠多了。第二,JS 只用来兜底检测是否是 iPhone X 系列(比如要动态调整其他样式)
比如你想在非 iPhone X 上把 padding 去掉,可以这样:
别试图读
window.safeAreaInsets,那玩意儿是 Safari 14+ 才加的实验性属性,根本不能当生产用。我见过团队直接用它做兼容判断,上线后 iOS14 以下用户全崩,真是追悔莫及。最后提醒一句:
constant()是 iOS 11-12 的旧写法,早就该扔了,现在全用env(),CSS 搞定的事,别让 JS 去背锅。window.safeAreaInsets这个API,所以会报undefined错误。稳妥的做法是结合CSS环境变量和JavaScript动态检测来做适配。首先在HTML的meta标签里加上viewport-fit=cover,这一步很关键,不然CSS的安全区域变量不会生效:
然后修改你的样式代码,用env(safe-area-inset-bottom)来设置padding,这是标准的安全区域变量:
至于JS部分,你需要做版本兼容判断。直接访问
window.safeAreaInsets可能会报错,建议这样写:这里用了parseFloat来防止注入攻击,确保取到的是数值。另外要注意,即使设置了这些,有些老旧webview可能还是不支持,最好让用户升级系统或者使用最新的浏览器。
最后提醒一下,测试的时候别只看模拟器,真机的表现可能会有差异,尤其是第三方app内置的webview环境。我之前就被坑过好几次,老版本的webview各种奇葩问题,建议做好降级方案。