textarea height 不生效的根本原因是默认 content-box 导致浏览器 ua 样式中 padding/border 叠加不一致,必须全局设 box-sizing: border-box;rows/cols 不可靠,应优先用 css height 配合 resize: none 和 overflow-y: auto;自适应高度需 js 监听 input 动态设置。

直接设 height 不生效,是因为 textarea 默认用 content-box,而各浏览器对 padding 和 border 的 UA 值不同——Chrome 约 2px 内边距,Firefox 约 4px,Safari 可能再加 1px;不统一 box-sizing,尺寸就永远不可控。
textarea height 不生效?先强制 box-sizing: border-box
你写的 height: 120px 在 Chrome 里可能变成 128px,在 Firefox 里变成 132px,根本原因不是“计算误差”,而是浏览器各自按自己的 UA 样式叠加 padding 和 border 后,又只把 height 当作内容区高度算。必须加:
textarea {
box-sizing: border-box;
}
这不是可选项,是底线。只写在局部规则里不够稳妥,建议全局统一:
*,
*::before,
*::after {
box-sizing: border-box;
}
否则动态插入的 textarea 或 Shadow DOM 里的实例可能漏掉。
为什么不能只靠 rows 和 cols 控制大小
rows 和 cols 是 HTML 属性,不是 CSS 尺寸控制手段。它们依赖字体、字号、行高、甚至浏览器内部行距算法,同一数值在 Chrome/Firefox/Edge 下渲染高度偏差常达 8–12px。更麻烦的是:
-
rows="5"在 Safari 下可能因line-height解析异常导致文字贴顶 - 当用户缩放页面时,
rows值不会响应式缩放,但 CSSheight会 - React/Vue 中若用
v-model或value绑定,rows不会随内容自动更新
禁用拖拽 + 防溢出:两个必须配对的声明
用户右下角拖拽会破坏布局,尤其在 flex/grid 容器中。只写 resize: none 还不够,因为内容超长时若没设 overflow-y,可能被裁剪或触发意外换行:
-
resize: none:彻底隐藏拖拽手柄,推荐首选(默认值是both) -
overflow-y: auto:内容超限时才出现滚动条;设hidden会丢内容,设scroll则永远显示空白滚动条 - 别只设
max-height而不设resize: none——拖拽图标还在,用户会误点
自适应高度?别信 field-sizing: content
Chrome 123+ 加了这个实验性属性,但它目前仅 Chrome 支持,且有硬伤:
- Safari/Firefox 完全无视,页面在这些浏览器里直接塌成一条线
- 空内容时高度为 0,除非显式设
min-height - React 中
useState更新后,scrollHeight可能滞后一帧,导致高度跳变 - 表单提交时,某些版本 Chrome 读不到
value的最新状态
生产环境请用 JS 方案:监听 input 事件,读 scrollHeight,再写回 style.height —— 稳定、可控、跨浏览器。
真正容易被忽略的,不是“要不要加 box-sizing”,而是它是否在所有上下文里都生效:iframe 里的 textarea、第三方组件封装的输入框、动态 innerHTML 插入的节点——这些地方的样式链往往断裂,得单独确认或覆盖。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











