必须同时设置 viewport-fit=cover 和 env(),否则 iOS Safari 不注入 safe-area 变量;仅 CSS 中写 env() 无效,需 meta 标签启用 viewport-fit=cover 才生效。

必须同时写 viewport-fit=cover 和 env(),缺一不可
只在 CSS 里写 padding-bottom: env(safe-area-inset-bottom) 永远不会生效——iOS Safari 只有在 <meta name="viewport" content="..., viewport-fit=cover"> 存在时,才注入 env() 变量;否则所有值都是 0px。
常见错误现象:getComputedStyle(document.body).getPropertyValue('padding-bottom') 返回 "0px",DevTools 模拟正常但真机完全没反应。
-
viewport-fit=cover是前提,不是可选项;漏掉它,env()就是摆设 - 微信、QQ 浏览器等旧 WebView 基本不支持
viewport-fit,此时env()直接被忽略,别指望它起作用 - 推荐用
@supports (padding-bottom: env(safe-area-inset-bottom))检测,比 UA 判断可靠得多
padding-bottom: env() vs margin-bottom: env(),选哪个?
对底部固定栏(如 position: fixed; bottom: 0 的 tabbar),padding-bottom 更稳妥;margin-bottom 容易引发布局错位或额外滚动高度。
原因:padding 是“撑开”内容区域,符合“留出可点击空间”的意图;margin 是把整个容器往外推,在 flex 或 absolute 场景下容易破坏流式布局。
立即学习“前端免费学习笔记(深入)”;
- 普通块级容器(如
<footer>)用padding-bottom: 20px; padding-bottom: env(safe-area-inset-bottom) - fixed 底部栏若需离底边固定距离(比如 8px),不要写
bottom: calc(8px + env(safe-area-inset-bottom))—— Safari 15.4 之前不支持单位混合运算,整条声明会被丢弃 - 真正安全的写法是:先设
padding-bottom: env(safe-area-inset-bottom),再用内边距或子元素 margin 控制净间距
用 tailwindcss-safe-area 插件省掉手写 env() 的麻烦
手动写 fallback + env() 组合容易漏、难维护,tailwindcss-safe-area 提供了语义化类名,比如 pb-safe、pb-safe-offset-4、pb-safe-or-8,背后自动处理 fallback 和多端兼容逻辑。
它不是简单映射,而是基于 env(safe-area-inset-*) 动态生成 padding/margin/height 类,并支持 offset 和 or(最小值)两种模式。
- 安装后只需在
tailwind.config.js中启用插件,无需改 HTML 结构 -
pb-safe对应padding-bottom: 20px; padding-bottom: env(safe-area-inset-bottom) -
pb-safe-or-8等价于padding-bottom: max(20px, env(safe-area-inset-bottom)),适合既要安全区又要最小留白的场景 - 注意:该插件不解决 WebView 兼容问题,仍需配合
@supports或降级策略
哪些地方必须加安全区适配?别全局套
安全区不是“全页面加 padding”,而是精准作用于交互密集区:输入框、操作按钮、TabBar、视频控制条。这些地方一旦被遮挡,用户第一反应是“点不动”,不是“页面坏了”。
对 <body> 直接加 env() padding 是反模式——它会影响所有内容,且无法局部控制,还可能和第三方组件冲突。
- 优先给
<main>、<footer>、<nav>等容器加pb-safe或对应类 - 避免
text-sm+text-gray-400这类低对比组合出现在安全区边缘,小字号+低对比是 WCAG 失败高发区 - 真机调试时,重点检查 iPhone X/XS/12/14 系列底部 Home Indicator 是否遮住按钮,模拟器常骗人


















