You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Textarea高度每次递减2px?仿通讯框高度异常排查

问题描述

我希望实现一款类似即时通讯软件的textarea组件:默认1行高度,文本溢出时自动扩展至2-4行。为此编写了如下代码:

function onInputHandle() {
    textarea.style.height = textarea.scrollHeight + "px";
}

该代码在文本行数增加时表现正常,但删除字符使文本不再溢出时,高度无法直接恢复至默认值(例如34px),而是每次递减2px,逐步降至34px,相关运行日志如下:

// 添加字符时
textarea.style.height: 34px
textarea.scrollHeight: 34
------------------- 
textarea.style.height: 34px 
textarea.scrollHeight: 34 

// textarea溢出,新增一行
-------------------
textarea.style.height: 55px
textarea.scrollHeight: 55
-------------------

// 删除字符后不再溢出,本应恢复为34px,却逐步递减2px
------------------- 
textarea.style.height: 53px
textarea.scrollHeight: 51
-------------------
textarea.style.height: 51px
textarea.scrollHeight: 49
------------------- 
textarea.style.height: 49px
textarea.scrollHeight: 47
-------------------
textarea.style.height: 47px
textarea.scrollHeight: 45
------------------- 
textarea.style.height: 45px
textarea.scrollHeight: 43
-------------------
textarea.style.height: 43px
textarea.scrollHeight: 41
------------------- 
textarea.style.height: 41px
textarea.scrollHeight: 39
-------------------
textarea.style.height: 39px
textarea.scrollHeight: 37
------------------- 
textarea.style.height: 37px
textarea.scrollHeight: 35
------------------- 
textarea.style.height: 35px
textarea.scrollHeight: 34
 ------------------- 
textarea.style.height: 34px
textarea.scrollHeight: 34
------------------- 
textarea.style.height: 34px
textarea.scrollHeight: 34 

可复现问题的完整代码示例

JavaScript

const ta = document.querySelector(".ta");

ta.addEventListener("input", () => {
  console.log(`textarea.style.height: ${ta.offsetHeight}`);
  console.log(`textarea.scrollHeight: ${ta.scrollHeight}`);
  console.log("-------------------");
  ta.style.height = `${ta.scrollHeight}px`;
});

CSS

.ta {
/*   height: 34px; */
  resize: none;
}

HTML

<textarea class="ta"></textarea>

请问该异常现象的原因是什么?


原因分析

这个问题的核心在于**scrollHeight的计算逻辑和当前高度设置方式不匹配**:

  1. 当textarea被手动设置为高于默认值的高度(比如日志里的55px)后,即便删除字符让内容只需要1行高度,浏览器计算scrollHeight时会受当前元素高度影响——此时scrollHeight不会直接返回内容的真实高度(34px),而是返回「当前元素高度减去未被内容填充的多余空间」。由于textarea默认带有上下边框(总高度通常为2px),每次将高度设置为scrollHeight时,相当于把元素高度削减了2px。

  2. 你没有在计算新高度前重置textarea的高度为默认状态,导致浏览器无法立刻算出内容的真实高度。当前逻辑是直接基于当前的scrollHeight更新高度,而当元素高度大于内容高度时,scrollHeight会返回一个介于「内容真实高度」和「当前元素高度」之间的值,于是就出现了每次删除字符,高度递减2px的情况,直到最终回到内容的真实高度。

如果要解决这个问题,只需要在获取scrollHeight前,先把textarea的高度重置为auto或者初始默认值,让浏览器重新计算内容的真实高度,再设置新高度即可。


内容的提问来源于stack exchange,提问作者b3rry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:42:51