应使用 css env(keyboard-inset-bottom) 替代 less 变量实现键盘避让,配合 viewport-fit=cover 元标签,支持 ios 16.4+/chrome 120+;老系统需 js 注入 css 自定义属性。

输入框被虚拟键盘遮挡时,Less 无法动态响应高度变化
Less 是编译时预处理器,height、calc() 中的变量在 CSS 输出后就固化了,它根本不知道手机弹出虚拟键盘后 window.innerHeight 缩小了多少。所以指望用 @keyboardHeight: 250px 这类静态变量去“适配”,本质是走不通的。
真正要解决的是:让输入框始终位于键盘上方、且不依赖 JS 监听却能响应视口变化——这必须靠运行时 CSS 能力,不是 Less 的职责。
- Less 编译后生成的是静态 CSS,所有变量都已替换完毕,
@vh: 100vw这类写法不会随屏幕缩放实时更新 - 移动端虚拟键盘触发的是
resize事件,只有 JS 或原生 CSSenv(height)/lh等环境函数才能捕获 - 强行在 Less 里模拟“动态”(比如用媒体查询分段写
@media (max-height: 600px))既不可靠,又无法覆盖各种机型和横竖屏切换场景
用 env(keyboard-inset-bottom) 替代 Less 变量做底部留白
iOS 16.4+ 和部分安卓 WebView(Chrome 120+)已支持 env(keyboard-inset-bottom),它是浏览器原生暴露的运行时键盘高度,可直接用于 padding-bottom 或 margin-bottom,无需 JS 干预。
配合 viewport-fit=cover 声明,就能让底部输入框自动上浮:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
CSS 中这样写即可生效(注意:不要用 Less 变量包裹它):
.input-container {
padding-bottom: env(keyboard-inset-bottom, 0px);
/* fallback for older iOS */
padding-bottom: max(0px, env(keyboard-inset-bottom, 0px));
}
-
env(keyboard-inset-bottom)返回值是带单位的长度(如300px),不能直接参与 Less 数学运算 - 必须加
viewport-fit=cover,否则 Safari 不会注入该环境变量 - Android 支持度仍不稳定,需搭配
android:windowSoftInputMode="adjustResize"原生配置才更可靠
需要兼容老系统?用 JS + CSS Custom Property 动态注入高度
当目标环境不支持 env()(如 iOS resize,把计算出的可用高度写入 CSS 自定义属性,再由 CSS 使用——这时 Less 只负责写好基础结构,不参与计算。
示例逻辑:
function updateViewportHeight() {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
window.addEventListener('resize', updateViewportHeight);
updateViewportHeight();
然后在 CSS(或 Less 文件中)直接使用该变量:
.input-container {
height: calc(var(--vh, 1vh) * 100 - 60px); /* 减去 header 高度等固定值 */
}
- 不要在 Less 里写
@vh: ~"calc(var(--vh, 1vh) * 100)";—— Less 会尝试编译这个字符串,报错或无效 - JS 注入的
--vh是运行时值,CSS 的calc()才真正执行计算,二者分工明确 - 务必在
resize后调用一次updateViewportHeight(),避免首屏未触发导致初始高度错误
Less 在这个问题里唯一靠谱的用途:组织 fallback 样式和响应式断点
Less 适合干的事,是把不同平台的 fallback 规则归拢清楚,比如为不支持 env() 的情况统一降级到固定间距,或按设备类型加载不同布局。
例如,用 Less 的条件混合(mixin)封装多端适配逻辑:
.keyboard-fallback(@platform: ios) when (@platform = ios) {
.input-container { padding-bottom: 100px; }
}
.keyboard-fallback(@platform: android) when (@platform = android) {
.input-container { padding-bottom: 120px; }
}
.keyboard-fallback(ios);
- 这种写法只在编译期起作用,用于生成多套 CSS,不能替代运行时适配
- 实际项目中建议把这类 fallback 控制权交给构建工具(如 PostCSS 插件),比 Less 更灵活
- 最易被忽略的一点:很多团队花时间调试 Less 变量计算,却忘了检查
input元素是否被position: fixed或父容器overflow: hidden截断——这才是遮挡的常见真因
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











