本文介绍在 react 应用中实现 textarea 高度自适应的完整方案:使其默认撑满可视区域,内容超出时仅内部滚动、不导致整个页面出现多余滚动条。
本文介绍在 react 应用中实现 textarea 高度自适应的完整方案:使其默认撑满可视区域,内容超出时仅内部滚动、不导致整个页面出现多余滚动条。
在 React 项目中,为
根本原因在于:100vh 是视口高度,但 calc(100vh - 5rem) 并未扣除
或 .journal-page 的实际占用空间(如顶部导航、标题间距等),且 * { margin: auto } 会强制重置所有元素外边距,干扰高度计算逻辑。✅ 正确解法分两步:
1. CSS 层级修正(推荐静态方案)
移除危险的通配符重置,改用更安全的归零策略,并使用 flex 布局隔离 textarea 高度:
/* 替换原来的 * { margin: auto } */
* {
box-sizing: border-box;
}
body, html {
margin: 0;
padding: 0;
height: 100%;
}
.journal-page {
display: flex;
flex-direction: column;
min-height: 100vh;
padding: 4rem 22%;
/* 移除可能影响高度计算的 margin/padding 冲突 */
}
.date-title {
font-size: 2rem;
margin-bottom: 1.25rem;
flex-shrink: 0; /* 标题不压缩 */
}
.entry-input {
font-size: 1.125rem;
width: 100%;
border: none;
outline: none;
resize: none;
background-color: white;
/* 关键:flex 占据剩余空间,而非固定 vh 计算 */
flex: 1;
/* 内容溢出时仅 textarea 自身滚动 */
overflow-y: auto;
/* 防止内边距撑高容器 */
padding: 0.75rem;
}
2. React 动态适配(增强体验)
若需 textarea 随内容自动伸缩(如初始为空时紧凑,输入后扩展),可结合 useRef 和 useEffect 实现:
import { useRef, useEffect } from 'react';
function JournalEntry() {
const textareaRef = useRef<htmltextareaelement>(null);
useEffect(() => {
const adjustHeight = () => {
const el = textareaRef.current;
if (!el) return;
el.style.height = 'auto'; // 重置高度以重新计算
el.style.height = `${Math.min(el.scrollHeight, window.innerHeight - 120)}px`; // 限制最大高度
};
adjustHeight();
const handleInput = () => adjustHeight();
const el = textareaRef.current;
el?.addEventListener('input', handleInput);
return () => el?.removeEventListener('input', handleInput);
}, []);
return (
<div classname="journal-page">
<h2 classname="date-title">今日日记</h2>
<textarea ref="{textareaRef}" classname="entry-input" placeholder="开始书写..."></textarea>
</div>
);
}
export default JournalEntry;</htmltextareaelement>
⚠️ 注意事项:
- 避免在 textarea 上同时设置 height 和 min-height 冲突值;
- flex: 1 方案更稳定,适合“占满剩余空间”场景;动态调整更适合“随内容呼吸式伸缩”;
- 测试时务必在真实设备/响应式视图下验证,100vh 在移动端 Safari 中存在兼容性问题(地址栏显示/隐藏影响视口高度);
- 若使用 CSS-in-JS(如 styled-components),确保 &::placeholder 等伪元素不影响行高计算。
最终效果:页面无额外滚动条,textarea 在内容不足时撑满可用区域,内容溢出时仅其自身出现纵向滚动条,体验干净可控。











