box-sizing: border-box 是安全区适配的必要前提,确保 padding-bottom 正确撑开内容高度而非增加容器总高;必须显式设在主内容容器(如 #app)上,配合 calc(60px + env(safe-area-inset-bottom)) 实现兼容性最佳的底部留白。

box-sizing 本身不构建安全区,但它是安全区适配的必要前提
很多人以为 box-sizing 能直接参与 env(safe-area-inset-bottom) 的计算,其实不能。它的作用是确保你加的 padding-bottom 真正“撑开内容高度”,而不是让容器意外变高、触发滚动或破坏 flex 布局。漏掉它,padding-bottom: calc(60px + env(safe-area-inset-bottom)) 可能白加。
-
box-sizing: border-box必须显式设在应用了padding-bottom的那个容器上(比如#app或main),不能只靠全局重置 - 如果容器原本是
box-sizing: content-box(浏览器默认),那padding-bottom会额外增加容器总高度,导致内容被顶出视口、滚动条异常、IntersectionObserver判断失准 - 特别注意:在使用
height: 100vh或flex: 1的布局中,box-sizing错误会让整个高度计算崩掉——例如100vh - 60px后再加 padding,实际高度可能远超视口
padding-bottom + box-sizing: border-box 是最稳的组合
比起用 margin-bottom 或 JS 动态计算,纯 CSS 的 padding-bottom 配合 box-sizing: border-box 是目前兼容性最好、性能最高、也最不易出错的安全区留白方式。
- 给主内容容器(不是
body,而是包裹所有业务内容的div#app或main)设:box-sizing: border-box;padding-bottom: 60px;padding-bottom: calc(60px + env(safe-area-inset-bottom)); - 不要把
padding-bottom加在body上——它会影响全局,比如弹窗、Toast、第三方组件的定位基准 - 值中的
60px必须是你底部导航栏的真实高度(含padding和border,不含margin),否则留空不足或过多 - Safari 15.4 之前不支持
calc()混单位,所以必须拆成两行写;第二行会覆盖第一行,旧设备 fallback 到 60px,新设备拿到动态值
为什么不用 margin-bottom?
margin-bottom 在 fixed 底部导航场景下基本无效,而且容易埋雷。
-
margin-bottom会折叠(margin collapse),尤其在相邻块级元素之间,结果就是“好像没加” - 它不改变容器自身的
scrollHeight,导致滚动到底部时,最后一屏内容仍会被导航栏盖住 - 和
IntersectionObserver、getBoundingClientRect()等 API 行为不一致——这些 API 认的是padding定义的边界,不是margin - 如果你用的是 flex column 布局(
html/body → display: flex; flex-direction: column),margin-bottom对子项高度无约束力,flex: 1会无视它继续撑满
容易被忽略的关键点
真正卡住人的从来不是写几行 CSS,而是三个硬性依赖缺一不可:
立即学习“前端免费学习笔记(深入)”;
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">缺了这句,env(safe-area-inset-bottom)永远返回0px -
box-sizing: border-box没设在加padding-bottom的那个容器上,padding就只是“多出来的高度” -
padding-bottom加错了地方——加在body上、加在nav自身上、或者加在某个中间 wrapper 但该 wrapper 没占满高度,都会失效


















