rows="1"仅用于归一化初始高度,真正实现自适应需配合js动态设置style.height为scrollheight,并严格遵循先设'auto'再读取的三步顺序,辅以min/max-height、box-sizing:border-box等css控制。

rows="1" 是自适应高度的起点,不是终点
直接设 rows="1" 只是为了让 scrollHeight 计算更干净——它把初始渲染高度“归一化”,避免因默认行数(如 rows="4")引入额外 padding 和 line-height 偏差。但这一步本身不产生自适应效果,必须配合 JS 读取 scrollHeight 才生效。
常见错误是以为只写 rows="1" + min-height 就能自适应,结果输入几行后内容被截断或滚动条弹出。真正起作用的是后续的 JS 动态赋值逻辑。
-
rows="1"要和style.height = 'auto'配合使用,否则scrollHeight在 iOS/IE11 上会卡住 - 不能同时写
style.height = '100px'和rows="1",内联 height 会完全屏蔽 rows 的计算作用 - React/Vue 中绑定
rows属性会导致每次 re-render 触发重排,光标跳动,应避免直接响应式绑定
scrollHeight 赋值前必须先清空 height
这是最常被跳过的关键步骤。如果 textarea 上次输入后留有 style.height = "120px",再执行 textarea.style.height = textarea.scrollHeight + 'px',浏览器会把旧 height 当作约束,导致新高度计算偏小——尤其在 iOS Safari 和 IE11 上,删文字后高度不缩、粘贴后底部留白都是典型表现。
正确顺序只有三步:textarea.style.height = 'auto' → textarea.offsetHeight(可选,触发重排)→ textarea.style.height = textarea.scrollHeight + 'px'。
- 必须用
scrollHeight,offsetHeight和clientHeight不含溢出区域,永远不准 - iOS 上建议包一层
requestAnimationFrame,比setTimeout(..., 0)更稳,尤其在高刷屏上 - IE11 需对换行符归一化:
textarea.value = textarea.value.replace(/\r\n/g, '\n'),否则空行末尾scrollHeight少算一行
min-height/max-height 必须走 CSS,不能靠 JS
JS 只负责把当前内容撑到刚好够用的高度,但空 textarea 不能塌成一条线,狂输时也不能无限拉伸——这两点必须由 CSS 的 min-height 和 max-height 控制。只靠 JS 算高度,等于把底线和上限全交给了运行时,一出错就是光标跳、高度卡、iOS 粘贴后留白。
推荐写法:min-height: 80px(保证初始有可点击区域)、max-height: 300px(超限时出现滚动条)、overflow-y: auto(否则内容被裁切)。
- 别写
height: 100%或flex: 1直接套在 textarea 上,会和 JS 设置的style.height冲突 -
box-sizing: border-box必须显式加,否则 padding 和 border 会让实际内容区变窄,scrollHeight计算失准 - 所有影响高度的样式(
font-size、line-height、padding)必须和 JS 计算时完全一致,Chrome 开发者工具里关掉 “user agent stylesheet” 再看 computed 值才可靠
resize 和 box-sizing 容易被忽略但直接影响体验
用户拖拽 textarea 边框会破坏 JS 自适应逻辑,导致高度固定、不再响应输入。这不是 bug,是浏览器行为:一旦用户手动拉伸,style.height 就被覆盖,后续 JS 赋值失效。所以要么禁用拖拽(resize: none),要么只允许垂直拉(resize: vertical)并确保 min-height 足够。
box-sizing: border-box 看似小事,但漏掉就会让 padding 挤占内容宽度,尤其在 width: 100% 场景下,右边出现横向滚动条或文字被遮挡。
-
resize: none时,min-height必须设得足够(比如 ≥ 80px),否则空 textarea 点击区域太小 -
resize: vertical时,要同步加max-height,否则用户拉到底后 JS 失效,高度就锁死了 - 字体变更(比如从
system-ui换成monospace)会改变行高,必须同步调整line-height,否则scrollHeight偏差肉眼可见
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











