textarea的scrollHeight无法低于3行?如何实现降至1行?
问题原因及解决办法
为啥scrollHeight降不下去?
- 父容器
.outerdiv设置了min-height:40px,同时开启align-items:center的flex布局,这会强制textarea高度至少填满父容器最小高度,没法收缩到1行。 handleChange函数只在输入内容有长度时执行计算,删到内容变少或为空时,完全没更新promptLines状态,导致textarea的rows属性一直停留在之前的3行。- textarea本身设置了固定
height:1rem,和flex布局叠加后进一步限制了高度收缩。
怎么改成能缩到1行?
第一步:调整CSS
修改.outerdiv和textarea的样式,去掉不必要的高度限制,调整flex对齐方式:
.outerdiv{ display: flex; align-items: flex-start; /* 改为顶部对齐,避免强制撑高 */ padding: 10px; border-radius: 25px; border: 2px solid #ccc; transition: border-color 0.5s ease; width: 80%; margin: auto; margin-bottom: 15px; margin-top: 10px; box-sizing: border-box; min-height: fit-content; /* 换成自适应内容的最小高度 */ } .outerdiv textarea{ flex: 1; border: none; border-radius: 25px; outline: none; font-size: 16px; font-family: sans-serif; resize: none; padding: 6px; min-height: 23px; line-height: 23px; /* 去掉固定height:1rem,让高度由rows和内容决定 */ }
第二步:修复React组件逻辑
用React的useRef代替getElementById,完善handleChange逻辑,不管内容多少都更新行数,空内容时重置为1行:
import React, { useState, useRef } from "react"; const App: React.FC = () => { const [promptLines, setPromptLines] = useState<number>(1); const talkInputRef = useRef<HTMLTextAreaElement>(null); // 用ref获取textarea const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { const inputContent = e.target.value; const talkInput = talkInputRef.current; if (!talkInput) return; const lineHeight = parseInt(window.getComputedStyle(talkInput).lineHeight); // 计算行数,空内容时直接设为1 let lines = 1; if (inputContent.length > 0) { const scrlht = talkInput.scrollHeight; lines = Math.floor(scrlht / lineHeight); // 防止行数小于1 lines = Math.max(lines, 1); } setPromptLines(lines); }; return ( <div className="outerdiv"> <textarea ref={talkInputRef} rows={promptLines} onChange={handleChange}></textarea> </div> ); } export default App;
修改后,输入内容时textarea会自动增高,删除到空或单行内容时,会自动收缩回1行。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

