真正起作用的是 css 环境变量 env(safe-area-inset-bottom),需配合 viewport-fit=cover 的 viewport 声明;媒体查询无法检测小黑条或全面屏,@supports 仅用于检测 env() 支持性并降级兼容,实际适配应直接在具体元素上应用该变量。

媒体查询本身不能直接检测底部小黑条高度,也不能识别“是否为全面屏”——它没有对应的 media feature。真正起作用的是 CSS 环境变量 env(safe-area-inset-bottom),配合正确的 viewport 声明和合理布局方式来实现底部间距预留。
必须加 viewport-fit=cover 才能启用 safe-area 变量
只写媒体查询(比如 @media (min-height: 812px) 或 @supports (padding-bottom: env(...)))无法让 env(safe-area-inset-bottom) 生效。关键前提是:
-
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">必须完整存在,缺任何一项(如漏掉width=device-width)都可能导致失效 -
viewport-fit=cover是开关:不加它,env()恒为0px,无论什么机型、什么媒体查询都无效 - 部分 WebView(如旧版微信 8.0.22 之前、某些企业微信容器)会忽略或覆盖该 meta,需实测渲染后的 DOM 确认
用 @supports 检测 env() 支持性,不是检测机型
@supports 的作用是降级兼容,不是精准识别 iPhone X/XR/12/15 等机型:
- 正确写法:
@supports (padding-bottom: env(safe-area-inset-bottom)) - 它匹配的是浏览器是否支持
env()函数,而非“有没有小黑条”;iOS 11.2+ Safari、Chrome for iOS、新版 Edge 都支持 - 不支持时可 fallback 到固定值(如
padding-bottom: 34px),但注意:34px 是竖屏典型值,横屏仅约 21px,且不同机型略有差异
实际适配应落在具体元素上,而非 media query 决定逻辑
不要试图用媒体查询“判断是否需要加 bottom 间距”,而应统一用以下结构处理:
- 对
position: fixed; bottom: 0的底部栏:直接在其自身设置padding-bottom: env(safe-area-inset-bottom) - 对 flex 布局中靠
margin-top: auto推到底部的容器:把padding-bottom: env(safe-area-inset-bottom)加在它的父容器上 - 绝对禁止给
或加padding-bottom,否则整页下移,顶部状态栏区域可能露白或错位 - 如需额外留空(比如按钮离黑条再加 8px),Safari 15.4+ 可用
calc(8px + env(safe-area-inset-bottom));低版本需两行写法:padding-bottom: 34px后跟padding-bottom: calc(8px + env(safe-area-inset-bottom))(后者会覆盖前者)
别再用 constant(),也别依赖 UA 或分辨率硬编码
constant() 已被 WebKit 官方废弃(自 iOS 11.2 起移除),所有新项目应只用 env()。
- 基于 UA 字符串判断 iPhone X 系列(如含
iPhone10,3)不可靠:系统更新、用户代理伪造、第三方浏览器都会出错 - 仅靠屏幕高度(如
height: 812px)也不准:iPhone XR 是 896px,iPhone 12 Pro Max 是 926px,且安卓全面屏也有类似问题 - 真正可靠的依据只有运行时获取的
safe-area-inset-bottom值,它是系统动态返回的安全距离,随横竖屏、深色模式、辅助功能缩放实时变化











