
本文介绍如何使用 css flexbox 实现容器内三个垂直排列 div 的动态高度分配:前两个 div 可显隐切换,第三个 div 自动填充剩余空间并支持内部滚动,确保整体不溢出视口。
本文介绍如何使用 css flexbox 实现容器内三个垂直排列 div 的动态高度分配:前两个 div 可显隐切换,第三个 div 自动填充剩余空间并支持内部滚动,确保整体不溢出视口。
在构建响应式、无滚动条干扰的单页应用布局时,常需让内容区域严格适配容器高度(如 100vh),同时支持部分模块动态隐藏。核心挑战在于:当上层元素隐藏后,底层内容需自动伸展占满剩余空间,且自身内容超长时仅内部可滚动,而非整页溢出。
解决方案的关键在于 Flexbox 的弹性行为,而非传统 height: 100% 或 absolute 定位。以下是推荐实现方式:
✅ 正确结构与样式
.container {
display: flex;
flex-direction: column;
height: calc(100vh - 26px); /* 减去可能的顶部工具栏/边距 */
padding: 5px;
box-sizing: border-box;
}
/* 固定内容区(可隐藏) */
#fix-one,
#fix-two {
margin-bottom: 5px;
/* 不设固定高度,由内容撑开;隐藏时自动释放空间 */
}
/* 弹性主内容区 —— 关键! */
#flexible {
flex: 1; /* 等价于 flex-grow: 1,优先吸收剩余空间 */
overflow-y: auto; /* 内容超长时仅本区域滚动 */
background-color: #f0f0f0;
}
? 注意:flex: 1 比 height: 100% 更可靠——它明确声明“尽可能拉伸”,不受父容器是否设 height 影响,且天然兼容显隐切换(display: none 会从 flex 流中移除,剩余空间自动重分配)。
✅ JavaScript 控制显隐(轻量级)
function toggle(id) {
const el = document.getElementById(id);
el.style.display = el.style.display === 'none' ? 'block' : 'none';
}
配合 HTML 中的按钮即可实时测试效果:
<div class="container">
<div>
<button onclick="toggle('fix-one')">切换第一区</button>
<button onclick="toggle('fix-two')">切换第二区</button>
</div>
<div id="fix-one">...</div>
<div id="fix-two">...</div>
<div id="flexible">...</div>
</div>
⚠️ 常见误区与注意事项
- ❌ 避免对 .container 使用 height: 100% 而未设置其父级高度(如 html, body),否则计算失效;推荐直接用 100vh 或 100dvh(更安全的视口单位)。
- ❌ 不要给 #flexible 设 height: 100% —— 在 flex 容器中,这反而可能破坏弹性行为,导致滚动失效或高度塌陷。
- ✅ 使用 box-sizing: border-box 确保 padding/border 不额外增加尺寸。
- ✅ 若需兼容旧浏览器,可添加 -webkit-flex 等前缀(现代项目通常无需)。
- ✅ 对于移动端,建议用 100dvh 替代 100vh,避免 Safari 地址栏缩放导致的高度抖动。
✅ 总结
该方案以 语义清晰、零 JS 高度计算、天然响应式 为优势:
✅ 显隐任意固定区块,底部区域自动伸缩;
✅ 滚动限制在目标 div 内,不触发页面级滚动;
✅ 代码简洁,易于维护与扩展(如增加第四个动态区块亦只需加 flex: 0 或 flex: 1 即可);
✅ 完全基于标准 CSS,无框架依赖。
只要掌握 flex: 1 + overflow-y: auto 这一黄金组合,即可优雅解决绝大多数“容器内自适应填高+局部滚动”场景。










