viewport-fit=cover 是 env() 变量生效的前提,必须配合 width=device-width 和 initial-scale=1.0 写在 head 中首个 meta 标签;padding-bottom: env(safe-area-inset-bottom) 需直接作用于 fixed 工具栏自身;折叠屏须组合 fold-* 与 safe-area 变量,并为主内容显式留空。

viewport-fit=cover 是 env() 变量生效的前提
不加 viewport-fit=cover,env(safe-area-inset-bottom) 和 env(fold-bottom, 0px) 永远返回 0px。这不是浏览器 bug,而是规范行为:只有启用全屏渲染模式,系统才注入这些环境变量。
必须写成完整形式,缺一不可:<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
-
width=device-width写成device_width或width=deviceWidth→ 整个 viewport 失效,后续所有适配归零 -
initial-scale=1.0缺失 → 折叠动画中 Safari 视口高度抖动,底部栏跳动甚至消失 - 把这行标签放在
里任何<link>或<style></style>后面 → iOS 首次渲染按 980px 宽度解析,闪屏+文字缩放异常
padding-bottom: env(safe-area-inset-bottom) 必须加在工具栏自身上
不是加在 ,也不是加在工具栏的父容器,而是直接作用于固定定位的工具栏元素。目标是让内容“撑开”到安全区之上,而不是把整个栏往下推。
正确写法示例:
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 56px;
padding-bottom: env(safe-area-inset-bottom);
}
- 用
bottom: env(safe-area-inset-bottom)是无效的 —— Safari 会静默丢弃整条声明 - 只写
padding-bottom不设height→ 工具栏高度塌陷,尤其在旧版 Android WebView 中 - 用
calc(56px + env(safe-area-inset-bottom))覆盖height→ 导致横竖屏切换时高度突变,触发重排
折叠屏铰链避让要用 fold-* 环境变量,不能只靠 safe-area
iPhone 的 safe-area-inset-bottom 解决的是 Home Indicator,但折叠屏还有物理铰链——它可能出现在底部(横屏展开)、顶部(横屏合盖)或左右侧(竖屏折叠)。仅靠 safe-area 无法避让铰链区,文字/按钮会被劈开。
必须组合使用:
- 横屏展开态(如 Z Fold 展开):
padding-bottom: env(fold-bottom, 0px) - 竖屏展开态(如 Mate X):
margin-inline-start: env(fold-left, 0px) - 需裁剪掉铰链区域:
clip-path: polygon(0 0, calc(100% - env(fold-right, 0px)) 0, calc(100% - env(fold-right, 0px)) 100%, 0 100%)
所有 env() 第二参数(如 0px)是降级值,不支持时自动回退,但前提是父容器不能设 overflow: hidden,否则裁剪和留白都会被截断。
主体内容必须预留足够底部空间,不能只靠 fixed 定位
position: fixed 元素脱离文档流,正文滚动时会钻进底部栏下面。最简单可靠的解法是给主内容区显式留空:
.main-content {
padding-bottom: calc(56px + env(safe-area-inset-bottom) + env(fold-bottom, 0px));
}
- 用
margin-bottom替代padding-bottom→ 部分安卓 WebView 对 fixed 元素的 margin 计算不一致,留空失效 - 只靠 JS 动态计算并设置
style.paddingBottom→ 折叠动画过程中 innerHeight 抖动,导致留空忽大忽小 - DOM 结构上,底部栏必须是
的最后一个子元素,否则某些安卓 WebView 会因祖先overflow: hidden导致 fixed 元素被截断
折叠屏适配真正的难点不在写多少 CSS,而在于 viewport 初始化是否严格、env() 变量是否真正注入、以及主内容与固定元素之间是否做了语义化留空 —— 这三处任一出错,都会导致用户点不到按钮、文字被劈开、或整个底部栏在动画中消失。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











