textarea默认不自动撑高是因为其规范行为仅响应rows和固定height,内容超出即显示滚动条;css的height: auto无效,必须用js监听input等事件,先设height='auto'再读scrollheight动态赋值。

为什么 textarea 默认不自动撑高?
浏览器原生 textarea 只响应 rows 和固定 height,内容超出就出现滚动条——这不是 bug,是规范行为。它不会根据文字行数或换行自动调整高度,除非你手动干预。
常见错误是给 textarea 加 height: auto 或 min-height,但 CSS 无法读取文本行数,纯样式方案无效。
必须靠 JS 监听输入并动态计算高度。核心逻辑:用一个隐藏的 <div> 模拟相同字体、行高、内边距,把 <code>textarea 的值塞进去,取其 scrollHeight,再赋给 textarea。
用原生 JS 实现最小可用 autosize(无依赖)
以下代码兼容 Chrome/Firefox/Safari,不依赖任何库,适合轻量表单:
function autosize(textarea) {
const computed = getComputedStyle(textarea);
const lineHeight = parseInt(computed.lineHeight) || 20;
const padding = parseInt(computed.paddingTop) + parseInt(computed.paddingBottom);
const shadow = document.createElement('div');
shadow.style.position = 'absolute';
shadow.style.top = '-9999px';
shadow.style.left = '-9999px';
shadow.style.width = textarea.offsetWidth + 'px';
shadow.style.fontSize = computed.fontSize;
shadow.style.fontFamily = computed.fontFamily;
shadow.style.lineHeight = computed.lineHeight;
shadow.style.padding = computed.padding;
shadow.style.boxSizing = 'border-box';
document.body.appendChild(shadow);
const update = () => {
shadow.textContent = textarea.value || '\n';
textarea.style.height = Math.max(shadow.scrollHeight + padding, lineHeight + padding) + 'px';
};
textarea.addEventListener('input', update);
textarea.addEventListener('focus', update);
textarea.addEventListener('paste', () => setTimeout(update, 10));
update(); // 初始化
}
// 使用:
autosize(document.querySelector('textarea.autosize'));
- 必须监听
paste并加setTimeout,否则粘贴时value还没更新 -
shadow.textContent设为'\n'是为了保证空值时至少一行高度 - 不要在
resize事件里调用update(),窗口缩放不影响内容行数,没必要
用 autosize npm 包时的三个关键配置点
如果项目已用构建工具,推荐 npm install autosize,但它默认行为容易踩坑:
-
autosize(textarea)后必须确保textarea已挂载到 DOM,否则报错Cannot read property 'offsetWidth' of null - 若
textarea在display: none容器里(比如 Tab 切换页),首次显示时高度可能不准——需手动触发autosize.update(textarea) - 默认不处理
maxlength达限时的截断反馈,建议配合input事件校验:if (e.target.value.length > e.target.maxLength) e.target.value = e.target.value.slice(0, e.target.maxLength)
移动端 iOS Safari 的换行异常怎么修?
iOS Safari 对 textarea 的 input 事件触发有延迟,尤其软键盘收起后,常导致最后一行高度没更新。这不是 autosize 的问题,而是 WebKit 的输入事件缺陷。
解决办法只有两个:
- 监听
blur事件补一次update()(适用于非实时校验场景) - 改用
compositionend事件替代部分input:它在中文输入法确认后立即触发,比input更及时
别指望 CSS resize: none 或 overflow: hidden 能绕过这个问题——它们只是藏起滚动条,不解决高度计算缺失。
真正麻烦的是混合输入场景:用户先打英文,再切拼音,再回删……这时候光靠一个事件监听不够,得组合 input + compositionstart + compositionend + blur 四个钩子,才接近稳定。











