必须添加<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">并设置padding-bottom: env(safe-area-inset-bottom)于固定底部容器,否则iOS Safari默认viewport-fit=auto导致该值恒为0px,底部内容被Home Indicator遮挡。

直接用 padding-bottom: env(safe-area-inset-bottom) 就能解决,但前提是 viewport-fit=cover 必须生效,否则这个值永远是 0px。
为什么 env(safe-area-inset-bottom) 返回 0?
这不是 CSS 写错了,而是浏览器压根没启用安全区 API。iOS Safari 默认把网页限制在“安全显示区域”内(viewport-fit=auto),此时所有 safe-area-inset-* 变量都无效。
- 必须在
<head>中声明:<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> - 漏掉
viewport-fit=cover,哪怕其他代码全对,env(safe-area-inset-bottom)也恒为0px - 部分构建工具(如 Vite、Webpack 插件)会自动注入 meta 标签,但可能覆盖或忽略
viewport-fit,需手动检查最终 HTML 源码
padding-bottom 还是 bottom?
别给 fixed 按钮设 bottom: env(safe-area-inset-bottom) —— 它不生效,且在旧版 Safari 会直接丢弃整条规则。
-
env()只对padding和margin属性有效,不能用于top/bottom/left/right - 正确做法:把
padding-bottom加在内容容器上(如#app或main),把内容“顶上来”,留出底部空间 - 不要加在
body或html上,否则整个页面下移,顶部状态栏区域也可能错位 - 务必配合
box-sizing: border-box,否则padding会让容器总高度超出预期
如何兼容 iOS 11.0–11.2?
新版用 env(),老版本只认 constant(),两者必须共存,且顺序不能错。
立即学习“前端免费学习笔记(深入)”;
- 写法必须是:
padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); - 顺序反了(
env在前)会导致 iOS 11.2 以下直接忽略该声明 - 如果还要叠加固定高度(比如按钮本身高 60px),旧版 Safari 不支持
calc(60px + env(...)),得拆成两行降级:padding-bottom: 60px; padding-bottom: calc(60px + env(safe-area-inset-bottom));
软键盘弹出后按钮又被顶穿怎么办?
CSS 无解。iOS Safari 和微信 WebView 的 env(safe-area-inset-bottom) 在键盘弹出时不会更新,但视口高度会缩,导致原本预留的 padding-bottom 过大,内容被顶到屏幕中间。
- 这是已知限制,不是你漏写了什么
- 必须用 JS 监听
visualViewport.resize,动态计算被遮挡高度:window.innerHeight - visualViewport.height - 然后实时设置按钮的
style.bottom,让它“浮”在键盘上方 - 安卓 WebView 完全不支持
keyboard-inset-bottom,也不响应visualViewport,只能靠结构优化(比如改用position: sticky)或预估高度 fallback
真正容易被忽略的是:安全区高度是动态的——横屏、视频全屏、CarPlay 连接等场景下,env(safe-area-inset-bottom) 可能从 34px 变成 0px 或 21px,硬编码任何固定值都会在某个时刻失效。


















