100vh在键盘弹出时失效是因为浏览器将软键盘视为视口一部分并重算vh,ios safari和部分安卓webview中window.innerheight不更新、resize不触发,但visualviewport.height已收缩,导致100vh容器仍撑全屏而遮挡input。

为什么100vh在键盘弹出时失效
不是CSS写错了,是浏览器把软键盘当成“视口的一部分”临时重算了vh。iOS Safari和部分安卓WebView在键盘弹出时,window.innerHeight不更新、resize事件不触发,但visualViewport.height已收缩——结果就是height: 100vh的容器还撑着全屏高,底部input直接被截断或遮挡。
实操建议:
- 别用height: 100vh做全屏容器高度
- 改用min-height: 100dvh + max-height: 100dvh + overflow-y: auto
- 必须配<meta name="viewport" content="width=device-width, initial-scale=1.0">,否则dvh退化为不可靠行为
- 老版本兼容:监听focusin/blur,动态切换class,层叠min-height: 100vh和height: 100dvh
fixed底部按钮被键盘盖住怎么修
这不是z-index没加够,而是position: fixed仍按原始视口定位,而键盘已压缩可视区域。iOS会把按钮“钉”在屏幕物理底部,Android WebView则行为碎片化。
实操建议:
- 首选position: sticky; bottom: 0:不脱离文档流,随滚动自然响应,iOS 15.4+/Chrome 90+支持良好
- iOS 16.4+可用bottom: env(keyboard-inset-bottom, 0px),但必须@supports (bottom: env(keyboard-inset-bottom))降级
- 安卓完全不支持env(keyboard-inset-bottom),fallback方案是给最外层容器加padding-bottom: 60px(按按钮实际高度设)
- 避免对body加margin-bottom,易触发外边距合并
scrollIntoView在fixed元素上为啥不生效
因为position: fixed元素脱离文档流,scrollIntoView找不到有效滚动上下文,尤其在iOS上常只滚到键盘边缘,而非输入框顶部。
实操建议:
- 别对fixed元素直接调element.scrollIntoView()
- 改监听focus,手动算偏移:window.scrollTo(0, inputEl.getBoundingClientRect().top - 100)(减去预估键盘高度)
- 更稳做法:给input父容器设scroll-margin-bottom: 120px,再调element.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
- 注意微信安卓版不支持scroll-margin-bottom,需降级为JS滚动
flex布局下内容被压缩、min-height不生效
用display: flex; flex-direction: column做页脚吸底时,键盘弹出会挤压中间区域,导致文字缩成一条线——根本原因是flex子项默认flex-shrink: 1,被强制压缩。
实操建议:
- 关键子项(如输入框容器)显式设flex-shrink: 0
- 容器用min-height: 100dvh而非height: 100dvh
- 确保子项min-height: 0(否则flex不会收缩,但也不该无限撑高)
- 若页面有transform或overflow: hidden,getBoundingClientRect()可能返回错误坐标,先用document.activeElement === inputEl确认焦点归属
真正麻烦的从来不是代码怎么写,而是不同设备对visualViewport、focus、resize的触发时机和精度差异——iOS可能延迟300ms才报告高度变化,安卓微信内置浏览器连visualViewport都不支持。得靠组合监听+降级兜底,而不是指望某一个API一劳永逸。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











