移动端输入框“自适应”指在不同屏幕、键盘弹出、横竖屏切换下仍可见、可点、不遮挡、不溢出;纯css可解大部分问题,但需明确边界:height:auto对input无效,field-sizing是伪属性,100vh在键盘弹出时失真。

移动端输入框“自适应”不是指宽度或高度自动跟着内容变,而是指在不同屏幕、键盘弹出、横竖屏切换等真实场景下,依然能被用户看见、可点击、不被遮挡、不溢出。纯 CSS 能解决大部分问题,但必须清楚边界——比如 height: auto 对 <input> 无效,field-sizing 是伪属性,100vh 在键盘弹出时会失真。
让输入框宽度随容器缩放(防水平溢出)
手机小屏上,<input> 和 <select></select> 默认有浏览器设定的固定宽度(如 130px–200px),父 <td> 或 <code><div> 缩小了,它们却不缩,直接撑破布局。
<ul>
<li>给所有表单控件加统一类名,例如 <code>class="form-control"
.form-control { width: 100%; max-width: 100%; box-sizing: border-box; },确保内边距不额外撑宽px 宽度;如果用了 flex 布局,flex: 1 比 width: 100% 更稳box-sizing,务必显式声明,否则 padding 会让实际宽度超 100%让多行输入框高度随内容伸缩(textarea 自适应)
<textarea></textarea> 不像 <div contenteditable> 那样原生支持内容驱动高度,<code>height: fit-content 在 iOS Safari 16.4+ 才稳定,老版本必须靠 JS 补位,但 CSS 层面仍需配合。
- 基础样式必须包含:
min-height: 44px; height: auto; resize: none; overflow: hidden; -
min-height设为 44px 是为了满足移动端最小可点击区域规范 - 禁用
resize防止用户拖拽破坏布局;overflow: hidden配合 JS 动态设高,避免滚动条闪现 - 别依赖
scrollHeight在 focus 瞬间取值——iOS 键盘弹出前视口未压缩,值偏大;建议在window.visualViewport?.addEventListener('resize', ...)或setTimeout(..., 300)后再计算
防止键盘弹出时输入框被遮挡(scroll-margin-bottom 生效条件)
scroll-margin-bottom 是目前最轻量、最可靠的方案,但它不是“写了就生效”,而是一套组合约束。
- 输入框必须在**可滚动容器内**:父级需设
overflow-y: auto且有明确高度,推荐min-height: 100dvh(Chrome 105+/Safari 16.4+),降级写法是min-height: 100vh; min-height: 100dvh; - 输入框自身不能脱离文档流:删掉
position: fixed、transform、perspective或will-change,否则getBoundingClientRect()坐标错乱,scroll-margin-bottom彻底失效且无报错 - Android 微信不支持该属性,必须 fallback:监听
focusin后调用input.scrollIntoView({ block: 'nearest', behavior: 'smooth' }) - 保险值设
scroll-margin-bottom: 120px(iOS 键盘约 200–250px,留余量防光标被盖)
底部固定按钮被键盘顶起怎么办
这不是 z-index 或定位层级问题,是 iOS 把 position: fixed 锚定在初始视口高度上,键盘一出,它就悬在半空。
- 首选
position: sticky; bottom: 0,前提是父容器有min-height: 100dvh,这样它会自然贴底且随内容滚动 - iOS 16.4+ 可用
bottom: env(keyboard-inset-bottom, 0px),但必须包裹在@supports (bottom: env(keyboard-inset-bottom))中,安卓完全不支持 - 安卓 fallback 推荐:最外层容器加
padding-bottom: 240px(实测常用值),并在blur时清空;别动body margin,它不阻止遮挡,还可能触发外边距合并
真正容易被忽略的是嵌套层级里的视觉副作用:只要任意父级有 transform 或 will-change,整个滚动锚点和坐标系统就不可信,scrollIntoView、scroll-margin-bottom、甚至 getBoundingClientRect 都会返回错误值,且控制台静默——查不到错,只看到效果不对。











