html如何实现文本框高度随内容自动增长的重点在于把前置条件、操作顺序和容易误判的地方分清楚。
textarea自动撑高需用JS监听input事件,先设height:auto,再将scrollHeight赋值给style.height,并配合min-height、box-sizing:border-box及空值重置等处理。
直接给 textarea 设 height: auto 没用——它不响应内容高度变化。必须靠 JS 监听输入并重设 scrollHeight,再同步赋给 style.height。
关键不是“让浏览器自动算”,而是“每次输入后主动读取真实内容高度并覆盖内联高度”。
input 事件(不是 keyup,后者捕获不到粘贴、剪切、拖入等操作)style.height,让元素恢复自然高度计算基准scrollHeight(含内边距,不含边框/外边距),再写回 style.height
box-sizing: border-box 统一尺寸参照系scrollHeight 是内容实际所需高度(包括溢出部分),clientHeight 是可视区高度(含 padding 不含 border/scrollbar),offsetHeight 是渲染后总高度(含 border + padding + scrollbar)。只有 scrollHeight 能准确反映“填满内容所需的最小高度”。
textarea 有 padding,scrollHeight 已包含它,无需额外加减border,不影响 scrollHeight 计算,但会影响视觉占比,建议统一用 box-sizing: border-box
scrollHeight 可能偏小,可加一次 setTimeout(() => {}, 0) 延迟读取不能直接改 DOM 的 style.height,否则和 React 的受控逻辑冲突;也不能只依赖 value 更新触发重排——需要手动同步高度。
useRef 拿到原生 textarea 元素useEffect 里绑定 input 事件(注意 cleanup)el.style.height = 'auto',再 el.style.height = el.scrollHeight + 'px'
自动撑高看似简单,但上线后常出现“突然跳一下”“撑太高”“缩不回去”——基本都卡在这几个点上。
scrollHeight 可能是 20px(行高+padding),导致太矮,建议设 min-height CSS 属性scrollHeight 不会回到单行高度,需判断 value.trim() === '' 后强制设回 min-height
scrollHeight 计算不准,可监听 fontload 或用 resize 事件兜底resize 监听并节流最麻烦的其实是换行符处理:Windows 的 rn、Mac 的 r、Linux 的 n 在不同浏览器中解析一致,但 textarea 的 value 总是标准化为 n,所以不用单独处理,放心用 value。