如何不使用flexbox让<div>填充容器剩余高度?
你碰到的这个问题我之前也踩过坑——用Flex实现父容器剩余高度填充后,嵌套的子元素想要用百分比高度时,必须逐层设置Flex布局,不仅代码越写越冗余,还违背了关注点分离的原则,确实挺闹心的。
为啥会出现这种情况?
当你给child-2设置flex-grow: 1时,它确实会占据容器的剩余高度,但这个高度是Flex容器动态计算出来的“拉伸高度”,并不是一个明确的height属性值。而CSS里的百分比高度,必须依赖父元素有明确的高度定义(或者说形成了“格式化高度上下文”),所以child-3的height: 80%找不到可以参考的父元素高度,自然就失效了。
方案1:给中间层明确设置高度(简单直接)
不用额外套Flex布局,只要给child-2加上height: 100%,同时确保父容器的高度是明确的就行:
.container { display: flex; flex-direction: column; height: 100vh; } .child-1 { flex-shrink: 0; /* 防止被压缩 */ height: 50px; } .child-2 { flex-grow: 1; height: 100%; /* 关键:明确高度,给子元素提供百分比参考 */ min-height: 0; /* 可选:如果child-3内容溢出需要滚动,加这个避免Flex容器限制 */ } .child-3 { height: 80%; /* 现在就能正常生效了 */ }
这样child-3就能正确参考child-2的高度计算百分比,不用再给child-2额外设置Flex。
方案2:用CSS Grid(更简洁的布局方式)
如果你的布局层级不复杂,CSS Grid能更直观地实现剩余高度填充,还能避免嵌套Flex的繁琐:
.container { display: grid; grid-template-rows: auto 1fr; /* 第一行自适应child1高度,第二行占满剩余空间 */ height: 100vh; } .child-1 { height: 50px; } .child-2 { /* 啥都不用额外设置,自动占满第二行的高度 */ } .child-3 { height: 80%; /* 直接生效,因为child-2的高度是Grid明确分配的 */ }
Grid的1fr会明确给child-2分配剩余空间,相当于给它设置了明确的高度,所以嵌套的子元素直接用百分比高度就行,不需要额外的布局设置。
方案3:CSS容器查询(现代浏览器专属)
如果你的布局需要更灵活的响应式处理,现代浏览器支持的CSS容器查询可以让子元素基于父容器的尺寸布局,不过这个方案更适合复杂组件场景:
.container { display: flex; flex-direction: column; height: 100vh; container-type: size; /* 声明父容器为尺寸容器 */ } .child-1 { flex-shrink: 0; height: 50px; } .child-2 { flex-grow: 1; } @container (height > 0) { .child-3 { height: 80%; /* 基于child-2的容器高度计算 */ } }
不过这个方案需要浏览器支持容器查询(Chrome 105+、Firefox 110+、Safari 16+),如果要兼容旧浏览器,前面两个方案更稳妥。
验证演示
我们把你的示例代码修改一下来验证效果:
html, body { margin: 0; } div { width: 100%; } .container { height: 100vh; display: grid; grid-template-rows: auto 1fr; } .child-1 { height: 50px; } .child-2 { } .child-3 { height: 80%; } /* 样式美化 */ .container { width: 100px; background: green; float: left; margin-right: 20px; } .child-1 { background: red; } .child-2 { background: magenta; } .child-3 { background: yellow; }
<div class="container"> <div class="child-1"> Child 1 </div> <div class="child-2"> Child 2<br> Seems like it works </div> </div> <div class="container"> <div class="child-1"> Child 1 </div> <div class="child-2"> Child 2 <div class="child-3"> Now it works! Child 3 fills 80% height of child 2. </div> </div> </div>
修改后,child-3就能正确占据child-2的80%高度,不用再逐层设置Flex布局了。
内容的提问来源于stack exchange,提问作者Nandin Borjigin

