ios safari底部栏遮挡fixed按钮的根本原因是100vh和bottom基于初始视口计算,解法是:用@supports包裹的100dvh替代100vh撑满真实可视高度;用env(safe-area-inset-bottom)避开手势条;用env(keyboard-inset-bottom)应对键盘弹出;三者均需viewport-fit=cover生效。

移动端 Safari 底部栏(地址栏/工具栏)会遮挡 position: fixed; bottom: 0 的按钮,根本原因不是样式写错,而是 iOS Safari 的 100vh 和 bottom 定位都基于初始 layout viewport 计算,不随地址栏收起/展开动态更新——按钮被“钉死”在初始视口底边,而用户实际可见区域变高后,按钮就沉到新露出的地址栏下方了。
用 100dvh 替代 100vh 撑满真实可视高度
这是目前最轻量、无 JS 的核心解法,但必须严格隔离使用:
-
100dvh是动态视口单位,iOS 16.4+ / Safari 16.4+ 原生支持,值随地址栏显隐实时变化 - 不能和
100vh写在同一 CSS 声明里,否则 Safari 会直接忽略整条规则 - 必须包裹在
@supports (height: 100dvh)中,并保留外部min-height: 100vh作为兜底 - 示例写法:
section.full-height {<br> min-height: 100vh;<br>}<br>@supports (height: 100dvh) {<br> section.full-height {<br> height: 100dvh;<br> }<br>}
用 env(safe-area-inset-bottom) 避开 iPhone 手势条
即使地址栏不遮挡,iPhone X 及后续机型的手势条(Home Indicator)也会盖住 bottom: 0 的按钮:
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
- 只对
padding-bottom或margin-bottom有效,不能直接用于bottom属性 - 必须配合
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">,否则env()返回0 - 推荐双写兼容老 Safari:
footer {<br> position: fixed;<br> bottom: 0;<br> padding-bottom: constant(safe-area-inset-bottom);<br> padding-bottom: env(safe-area-inset-bottom);<br>} - 安卓和旧 iOS 会忽略该声明,自动 fallback 为
0,无副作用
键盘弹出时用 env(keyboard-inset-bottom) 动态上浮按钮
软键盘弹出会压缩 visual viewport,但 fixed 元素仍按原始高度定位,导致被顶穿:
-
env(keyboard-inset-bottom)仅 iOS 16.4+ Safari 支持,返回键盘高度,可直接用于bottom - 必须用
@supports (bottom: env(keyboard-inset-bottom))降级,否则旧版解析失败 - 正确写法:
.btn-fixed {<br> position: fixed;<br> bottom: 0;<br>}<br>@supports (bottom: env(keyboard-inset-bottom)) {<br> .btn-fixed {<br> bottom: env(keyboard-inset-bottom);<br> }<br>} - 安卓完全不支持该变量,需用 JS fallback(如监听
focusin+visualViewport)或预留padding-bottom
真正容易被忽略的是:这三个 env() 和 dvh 方案全部依赖 viewport-fit=cover 这个 meta 属性生效;缺了它,所有环境变量都返回 0,且真机调试时很难一眼发现——Safari 开发者工具里 computed 样式不会报错,只会静默失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










