viewport-fit=cover是硬性前提,缺则env(safe-area-inset-bottom)恒为0px;需在meta中声明、padding-bottom加于内容容器、配合JS处理软键盘弹出等动态场景。

直接用 position: fixed + bottom: 0 在 iPhone 上必然被 Home Indicator 遮挡,这不是样式写错了,是漏了关键前提。
viewport-fit=cover 是 env() 生效的硬性前提
没有它,env(safe-area-inset-bottom) 永远返回 0px,所有后续计算都失效。这不是兼容性问题,是 Safari 的强制规则。
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">必须写在<head>最前面,不能遗漏initial-scale=1.0 - 安卓浏览器(Chrome、微信 WebView)完全不识别
viewport-fit=cover和env(),此处只保 iOS - 写成
viewport-fit: cover(CSS 属性)无效,必须是<meta>的 content 值
padding-bottom 要设在内容容器上,不是按钮本身
position: fixed 按钮脱离文档流,加 margin-bottom 或 padding-bottom 到它自己毫无意义——它不会推高内容区域,反而可能因 margin 折叠失效。
- 把
padding-bottom加到最外层内容容器(如#app、main或.page-content)上 - 必须声明
box-sizing: border-box,否则 padding 会让容器总高度超出预期 - 双写降级:先写
padding-bottom: constant(safe-area-inset-bottom),再写padding-bottom: env(safe-area-inset-bottom),旧版 Safari 认第一行,新版认第二行
软键盘弹出时 CSS 失效,必须靠 JS 补位
iOS Safari 和微信 WebView 在键盘弹起后,env(safe-area-inset-bottom) 不会更新,但视口高度缩了,导致原本留白的 padding-bottom 过大,内容被顶到屏幕中间。
立即学习“前端免费学习笔记(深入)”;
- 监听
focusin事件,在输入框获得焦点时临时移除内容容器的padding-bottom - 监听
focusout事件,在失去焦点时恢复padding-bottom - 更精细的做法是监听
visualViewport.resize,用window.innerHeight - visualViewport.height动态算出被遮挡高度,赋给按钮的bottom值
真正难的不是写出那两行 env(),而是意识到:iOS 安全区适配是个“三段式”问题——meta 控制变量可用、CSS 控制静态留白、JS 控制动态变化。漏掉任何一段,按钮就会在某个场景下消失或错位。


















