env()和constant()是CSS原生函数,用于读取iOS/安卓全面屏设备的安全区偏移量;移动端必须用它们适配刘海、Home Indicator等,因Less不解析这些函数,需通过calc()在运行时计算,且须双写constant()/env()实现兼容。

什么是env()和constant(),为什么移动端必须用它们
iOS 11+ 和部分安卓全面屏设备会预留安全区域(如刘海、Home Indicator),导致内容被遮挡。CSS 原生提供了 env() 和已废弃但旧版 Safari 仍需兼容的 constant() 来读取系统定义的安全区偏移量,比如 env(safe-area-inset-bottom) 表示底部安全区高度。
Less 本身不解析这些函数——它只是编译时预处理器,env() 必须原样输出到最终 CSS 中运行时生效。所以关键不是“Less 计算安全区”,而是“用 Less 正确包裹、复用、运算 env() 值”。
常见错误是写成:@bottom: env(safe-area-inset-bottom); margin-bottom: @bottom + 10px; —— 这会导致编译报错,因为 Less 尝试把 env() 当数值加减,而它实际是运行时字符串。
Less 中正确声明和复用 env() 值的方法
核心原则:把 env() 当作不可拆解的“原子值”,用变量存其字面量,所有运算放在 CSS 函数内完成(借助 calc())。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确写法:用字符串拼接生成完整
calc()表达式 - ✅ 推荐封装为 mixin,避免重复手写
calc() - ❌ 不要对
env()做 Less 算术(如@x + 10px),也不要用~""强转(易出错且不必要)
.safe-bottom(@offset: 0) {
padding-bottom: calc(env(safe-area-inset-bottom) + @offset);
}
// 使用
.footer { .safe-bottom(12px); }这样编译后就是 padding-bottom: calc(env(safe-area-inset-bottom) + 12px);,浏览器运行时才计算。
constant() 兼容写法与自动降级逻辑
iOS 11.0–11.1 仅支持 constant(),11.2+ 才支持 env()。现代方案是双写,后者覆盖前者:
.safe-top() {
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
}注意顺序:constant() 在前,env() 在后。不支持 env() 的旧 Safari 会忽略第二行,执行第一行;新版本则直接跳过已失效的 constant()(Safari 11.2+ 已弃用并静默忽略它)。
不要尝试用 Less 判断 iOS 版本做条件编译——UA 不可靠,且编译时根本不知道运行环境。
结合 Less 运算做动态适配的边界场景
真正需要 Less 参与运算的,是那些“基于安全区做比例调整”的逻辑,比如:底部按钮高度 = 安全区高度的 1.5 倍,但不得小于 44px。
- 不能写
calc(env(safe-area-inset-bottom) * 1.5)—— CSS 不支持env()乘除运算 - 可行方案:用 Less 计算基准值,再用
calc()做兜底比较
.fab-fixed() {
// 假设设计稿约定最小安全间距为 20px,按比例放大
@min-safe: 20px;
@scale: 1.5;
bottom: max(@min-safe * @scale, env(safe-area-inset-bottom));
// 注意:max() 仍需浏览器支持(Chrome 111+ / Safari 16.4+)
}更稳妥的做法仍是 calc() + 固定 fallback:bottom: calc(env(safe-area-inset-bottom) + 10px);,然后用媒体查询或 JS 检测补充复杂逻辑。
最易被忽略的一点:env() 返回值带单位(px),但某些安卓 WebView 或旧版 UC 可能返回 0 或空字符串——务必在关键区域加一层默认 fallback,比如 padding-bottom: calc(env(safe-area-inset-bottom) + 10px); padding-bottom: 10px;。


















