textarea自适应高度必须先设style.height='auto'再读scrollHeight,否则受旧高度干扰;iOS Safari需用requestAnimationFrame确保更新就绪;IE11需处理\r\n换行符偏差;CSS须设min-height、max-height、overflow-y和box-sizing。

textarea.style.height = 'auto' 必须在读 scrollHeight 前执行
不加这句,scrollHeight 就会受上一次固定高度干扰——比如上次设过 style.height = "200px",浏览器会把它当约束,导致这次计算偏小。iOS Safari 和 IE11 尤其明显:删文字时高度卡住、粘贴后底部留白、回车时光标跳动,全是这个原因。
正确顺序只有三步,缺一不可:
textarea.style.height = 'auto'- 再读
textarea.scrollHeight - 最后赋值
textarea.style.height = textarea.scrollHeight + 'px'
别用 offsetHeight 或 clientHeight 替代——它们不含溢出内容,永远撑不开。
移动端 iOS Safari 必须用 requestAnimationFrame 包一层
iOS Safari 对 scrollHeight 的更新有微小延迟,尤其在 120Hz 屏或粘贴大段文本后,高度常卡在旧值。这不是 bug,是渲染管线机制决定的。
立即学习“前端免费学习笔记(深入)”;
用 setTimeout(..., 0) 不够稳;requestAnimationFrame 才能等它真正就绪:
textarea.addEventListener('input', () => {
requestAnimationFrame(() => {
textarea.style.height = 'auto';
textarea.style.height = textarea.scrollHeight + 'px';
});
});
注意:不能只在初始化时调一次,每次 input 都得包,否则快速输入最后一行会“弹下来”。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
IE11 下 scrollHeight 偏小,要处理 \r\n 换行符
IE11 把 \r\n 当一个字符算,现代浏览器统一按 \n 处理,导致空行末尾的 scrollHeight 偏小约 1 行(实测常差 2px)。
两种修复方式:
- 若后端不要求保留原始换行:
textarea.value = textarea.value.replace(/\r\n/g, '\n'),再算高度 - 若必须保留
\r\n(如日志类场景):const height = textarea.scrollHeight + (isIE11 ? 2 : 0)
别漏掉检测逻辑:const isIE11 = !!window.MSInputMethodContext && !!document.documentMode。
min-height / max-height 和 box-sizing 必须靠 CSS 控制
光靠 JS 算高度不行。空 textarea 默认可能只有 20px 高,用户点不中;不限制上限,粘贴万字文档能把页面顶飞。
CSS 至少要写这四条:
-
min-height: 80px(保证初始可点击) -
max-height: 300px(超限时才出滚动条) -
overflow-y: auto(不写会裁切内容) -
box-sizing: border-box(确保 padding/border 不额外加高)
还容易忽略一点:所有影响高度的样式(padding、line-height、字体大小)必须和 JS 计算时完全一致。Chrome DevTools 里关掉 “user agent stylesheet”,看 computed 值才能确认真实渲染高度。


















