一次 H5 表单事故:100vh 在 Android 上到底坑在哪

我用 100vh 写的 H5,在 Android 上被软键盘"顶穿"了 😭

事情是这样的。

我用 height: 100vh 写了一个很普通的 H5 页面,

结构也很常规:上面是内容,下面是输入框。

在 iOS 上一切正常,

结果一到 Android,用户一点输入框------

👉 软键盘弹起,输入框直接被挡住。

那一刻我意识到:
又是 100vh 的锅。


问题复现:看起来很合理,其实已经埋雷了 💣

css 复制代码
.page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}
ini 复制代码
<input placeholder="请输入手机号" />

现象是这样的:

  • Android 软键盘弹起

  • 页面视觉高度明显变小

  • 但 .page 仍然是 100vh

  • 👉 输入框被键盘盖住,页面不滚动

用户:看不见怎么输?****

我:......****


深挖原因:不是你代码写错,是

100vh

理解错了 🤯

很多人(包括我以前)都会默认:

vh = 当前可视区域高度

但在 Android 浏览器 / WebView 里,真实情况是:

  • vh 取的是 初始布局视口高度

  • 软键盘弹起:

    • 改变的是"可视区域"

    • 不会重新计算 vh

一句话总结:

键盘变了,vh 没变。

所以你看到的就是:

  • 页面下面被键盘盖住
  • CSS 还以为自己是"满屏"

那些年我试过但不太靠谱的方案 🙃

❌ 方案一:监听

resize

javascript 复制代码
window.addEventListener('resize', () => {
  // 动态改高度
});

问题:

  • 有的 Android 触发,有的不触发
  • WebView 行为更是五花八门
  • 维护成本很高

❌ 方案二:

scrollIntoView

css 复制代码
input.scrollIntoView({ behavior: 'smooth' });

问题:

  • 治标不治本
  • 多输入框体验很怪
  • 页面高度逻辑本身还是错的

正确解法一:用

svh

,让页面"稳住" 🧘‍♂️

arduino 复制代码
.page {
  min-height: 100vh;
  min-height: 100svh;
}

为什么

svh

有用?

  • svh = 最小视口高度****

  • 软键盘弹起时:

    • 可视区域只会变小

    • 页面不会出现"被盖住却不滚"的情况

✅ 不抖

✅ 不需要 JS

✅ 非常适合表单 / 登录 / 支付页


正确解法二:沉浸式场景用

dvh 🎮

css 复制代码
.page {
  height: 100vh;
  height: 100dvh;
}

dvh 的特点是:

  • 视口变,它就变

  • 键盘弹起,页面高度立刻重新计算

适合:

  • 活动页

  • 视频页

  • 对高度变化有心理预期的页面

⚠️ 不太适合关键表单页(容易抖)


100%

能不能救?答案是:不能 🙅‍♂️

css 复制代码
.page {
  height: 100%;
}

原因很简单:

  • 100% 依赖父容器高度

  • 父容器通常还是 100vh

  • 本质问题没有变

一句话点醒自己:

100% 是布局单位,不是视口单位。****


我的最终推荐(直接抄作业 ✍️)

✅ 表单 / 登录 / 支付页

arduino 复制代码
.page {
  min-height: 100vh;
  min-height: 100svh;
}

✅ 沉浸式页面

css 复制代码
.fullscreen {
  height: 100vh;
  height: 100dvh;
}

写在最后

以前我们总想着:

用 JS 去修补浏览器的坑

但现在发现:

CSS 自己已经进化了,只是我们还在用旧认知。****

如果你也在 Android H5 上被软键盘折磨过,

希望这篇能帮你少掉几根头发 🧠✨

相关推荐
IT_陈寒2 分钟前
Python的线程池把我CPU跑满了,原来少传了个参数
前端·人工智能·后端
喜欢的名字被抢了11 分钟前
写-Chrome-扩展时踩过的那些-MV3-的坑
前端·chrome
网安老伯21 分钟前
网络安全基础要点知识介绍(非常详细),零基础入门到精通,看这一篇就够了
运维·前端·网络协议·web安全·网络安全·职场和发展
wuqingshun31415926 分钟前
springBoot是如何通过main方法启动web项目的?
前端·spring boot·后端
xxwl58526 分钟前
HTML 小总结:从骨架到枝叶,系统掌握网页结构
前端·html
●VON28 分钟前
鸿蒙 PC Markdown 编辑器 Bridge 协议:原生外壳与 Web 内核的状态同步
前端·华为·编辑器·harmonyos·鸿蒙
MrDJun1 小时前
分享一款免费实用的网页变动监控工具:PageWatch.tech
前端·javascript·vue.js
米码收割机1 小时前
【web】邻里悦站—社区便民服务平【独一无二】(源码+说明文档)
前端
程序员爱钓鱼1 小时前
Rust Option 详解:安全处理“可能存在,也可能不存在”的值
前端·后端·rust
程序员爱钓鱼1 小时前
Go Modules 包管理详解:go.mod、go.sum 与依赖管理
前端·后端·go