iPhone 上 fixed 元素被底部指示器遮挡,因 iOS Safari 的 fixed 定位不感知安全区域;需配合 viewport-fit=cover 才使 env(safe-area-inset-bottom) 生效,并按 constant()→env() 顺序书写兼容性声明。

为什么直接写 position: fixed; bottom: 0 在 iPhone 上会被遮挡
不是 CSS 写错了,而是 iOS Safari 的 fixed 定位只认物理视口底边,不感知安全区域——比如 iPhone X 及后续机型底部的 Home Indicator(约 34px 高)会直接盖住你的按钮。用户点不到,但 DevTools 模拟器里一切正常,真机一测就失效。
env(safe-area-inset-bottom) 必须配合 viewport-fit=cover 才生效
单独写 padding-bottom: env(safe-area-inset-bottom) 没用,iOS Safari 只有在 <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> 完整存在时,才会注入 env() 变量;否则返回 0px,相当于没写。
常见错误包括:
- 漏掉
viewport-fit=cover,只写了initial-scale=1.0 - 写了
viewport-fit=contain或没写这个参数 - meta 标签被 JS 动态覆盖或重复插入,导致实际生效的是旧版本
该用 padding-bottom 还是 margin-bottom?
对普通容器(如 <footer></footer>、<main></main>)优先用 padding-bottom:
立即学习“前端免费学习笔记(深入)”;
-
padding-bottom: env(safe-area-inset-bottom)让内容自然上浮,不破坏点击热区 -
margin-bottom: env(safe-area-inset-bottom)只适合position: fixed; bottom: 0的底部栏,且必须配合calc()控制净距离(例如bottom: calc(0px + env(safe-area-inset-bottom))) - 直接写
margin-bottom: env(safe-area-inset-bottom)会导致可滚动区域变大,手指一滑菜单就“掉出”视口
兼容 iOS 11.0–11.1 必须双写 constant() 和 env()
iOS 11.2+ 已废弃 constant(),但 11.0–11.1 不识别 env()。CSS fallback 顺序必须严格:
footer {
position: fixed;
bottom: 0;
padding-bottom: constant(safe-area-inset-bottom); /* iOS 11.0–11.1 */
padding-bottom: env(safe-area-inset-bottom); /* iOS 11.2+ & Chrome Android */
}注意:constant() 放前面,env() 放后面,浏览器会取最后一个有效声明;别反着写,否则老系统永远 fallback 到 0。
真正容易被忽略的点是:安全区变量在软键盘弹出、横竖屏切换、甚至地址栏收放时会动态变化,但只有 padding/margin 能响应重排,top/bottom 直接赋值 env() 在 Safari 中多数情况不更新——别信 demo 里静态截图,真机连按几次旋转再点输入框,才能验出问题。


















