移动端CSS获得手机上、下安全距离
calc(20rpx + env(safe‑area‑inset‑bottom)) 详解
env() 是CSS环境变量函数,safe‑area‑inset‑bottom 代表iOS全面屏底部手势条(小黑条)的避让高度,单位px。
你的写法含义:20rpx固定距离 + 系统给的底部安全区px距离,常用于小程序底部fixed悬浮按钮、底部栏的bottom / padding‑bottom。
一、四个安全区环境变量
env(safe-area-inset-top); /* 顶部刘海/灵动岛高度 px */
env(safe-area-inset-right); /* 右边避让,横屏生效 px */
env(safe-area-inset-bottom); /* 底部手势条高度 px */
env(safe-area-inset-left); /* 左边避让,横屏生效 px */- 非全面屏手机:
safe‑area‑inset‑bottom = 0px,表达式等价于calc(20rpx + 0),只会保留你的20rpx基础距离。 - iPhone全面屏:会自动叠加小黑条的高度(34px等)。
二、关键坑点(高频踩坑)
1️⃣ H5网页必须开启 viewport‑fit=cover
不加,safe‑area‑inset‑bottom 永远等于0,完全失效。
<meta name="viewport" content="width=device‑width,initial‑scale=1,viewport‑fit=cover">微信小程序不需要写meta,框架默认开启cover模式,直接可用。
2️⃣ 历史兼容:constant()(iOS11.2以前旧版本)
旧版Safari用constant(),新版本用env(),constant写在env上方,做降级兼容。
/* 兼容旧iOS */
padding‑bottom: calc(20rpx + constant(safe‑area‑inset‑bottom));
padding‑bottom: calc(20rpx + env(safe‑area‑inset‑bottom));3️⃣ calc内部符号两侧必须空格,否则直接失效
✅正确:calc(20rpx + env(safe‑area‑inset‑bottom))
❌错误:calc(20rpx+env(safe‑area‑inset‑bottom)) +两边没空格会解析失败。
4️⃣ 单位混用注意(小程序)
env(safe‑area‑inset‑bottom) 返回px;你写的是rpx。
微信小程序内部会自动做单位换算,calc(rpx + env(xxx))是支持直接写的,不需要手动转px,小程序引擎自动处理。
H5不支持rpx单位,H5要统一全部改成px。
5️⃣ env支持回退默认值(第二个参数)
设备不支持安全区变量时,使用回退值:
env(safe‑area‑inset‑bottom, 0px);示例:
padding‑bottom: calc(20rpx + env(safe‑area‑inset‑bottom,0px));三、两种业务场景示例(微信小程序)
场景1:底部fixed悬浮按钮,bottom定位
.fixed‑btn{
position: fixed;
bottom: calc(20rpx + env(safe‑area‑inset‑bottom));
right: 30rpx;
}含义:距离底部基础20rpx,iPhone全面屏再叠加手势条高度。普通安卓/非全面屏,就只有20rpx。
场景2:底部栏增加内边距padding‑bottom(推荐,避免内容被小黑条遮挡)
.footer‑bar{
padding‑bottom: calc(24rpx + constant(safe‑area‑inset‑bottom));
padding‑bottom: calc(24rpx + env(safe‑area‑inset‑bottom));
}四、常见错误现象排查清单
env完全不起作用:
- H5:检查meta有没有加
viewport‑fit=cover - 符号
+忘记加空格; - 顺序写反,
env写在constant前面。
- H5:检查meta有没有加
iPhone底部距离变得巨大:>
你写的是
基础距离 + safe‑area‑inset‑bottom,如果你本身元素已经靠到屏幕最底边,就不要额外再加基础值,直接写env(safe‑area‑inset‑bottom),否则会双重叠加,留白过大。
五、H5完整可复制样板
.bottom‑wrap {
padding‑bottom: calc(16px + constant(safe‑area‑inset‑bottom));
padding‑bottom: calc(16px + env(safe‑area‑inset‑bottom,0px));
}小程序直接复制,把px替换成rpx即可。