textarea自适应高度必须用JavaScript实现,CSS单独无法搞定;核心是监听input事件,先设height: auto触发重排,再赋scrollHeight值,并配合min-height、max-height等CSS限制边界。

textarea自适应高度必须用JS,CSS单独搞不定
Bootstrap 的 .form-control 对 textarea 只提供宽度 100%、圆角、阴影等样式,**不处理高度自适应**。设 height: auto 或 min-height 都没用——textarea 不像 div 那样随内容重排布局,它默认按 rows 固定行数撑开,且 scrollHeight 不会自动生效。
核心矛盾在于:浏览器只在“需要重排”时才准确计算 scrollHeight,而直接赋值 this.style.height = this.scrollHeight + 'px' 很容易读到过期值,尤其删减内容或粘贴后。
- 必须先触发一次重排(比如设
height: auto或极小值),再读scrollHeight - 监听
input事件足够覆盖输入、粘贴、剪切、拖入,但别只监听keyup(漏掉 paste) - Bootstrap 5+ 的
.form-control已设box-sizing: border-box,所以直接赋scrollHeight像素值即可,不用手动减 padding/border
最简可用的 JS 实现(含防卡顿和初始化)
以下代码能应对 iOS Safari、IE11、快速删减等典型问题:
const $ta = document.querySelector('textarea.form-control');
const adjustHeight = () => {
$ta.style.height = 'auto';
$ta.style.height = $ta.scrollHeight + 'px';
};
$ta.addEventListener('input', () => {
requestAnimationFrame(adjustHeight);
});
adjustHeight(); // 初始渲染后立即执行一次
关键点:
-
requestAnimationFrame确保在浏览器下一次重绘前读取scrollHeight,比setTimeout(0)更准,也比纯防抖更及时 - 初始调用
adjustHeight()防止首屏显示时高度过矮(比如 placeholder 挤在顶部) - 不加
requestAnimationFrame在 iOS 上易出现光标跳动、底部留白;不初始化则空值时可能只有 1 行高
必须配的 CSS:min-height / max-height / overflow
JS 控制高度只是半程,CSS 才决定边界和体验:
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
textarea.form-control {
min-height: 3.5rem; /* 至少显示 2–3 行,避免太矮 */
max-height: 200px; /* 防止万字粘贴把页面顶飞 */
resize: none; /* 关掉用户拖拽,否则破坏自适应 */
overflow: hidden; /* 隐藏滚动条,让伸缩更干净 */
}
注意:
-
min-height不能靠 JS 算——空textarea的scrollHeight在不同字体/缩放下差异极大,CSS 是唯一可靠方式 -
max-height必须设,否则长文本会让父容器(如.card-body)无限撑高,甚至溢出视口 - 如果父容器是
.col或.form-floating,检查是否设置了overflow: hidden(默认可能裁剪),需显式设为visible
form-floating 下长标签换行要额外加 CSS
当 textarea 套在 .form-floating 里,且 label 文字较长时,原生逻辑会让标签被截断或撑破布局。只需两处微调:
.form-floating > label {
white-space: normal;
line-height: 1.4;
padding-top: 0.25rem;
}
.form-floating .form-control {
height: auto;
min-height: 3.5rem;
}
这样既保持 form-floating 的浮动动画和语义,又让长标签自然折行、不重叠控件。不需要额外 wrapper、position: relative 或 JS 干预。
真正容易被忽略的是:所有这些调整都依赖于 scrollHeight 的准确性,而它对换行符(\r\n vs \n)、字体加载时机、zoom 缩放都敏感。上线前务必在 iOS Safari 和 Windows Edge(旧内核)上实测删减和粘贴场景。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










