用flex实现三栏垂直布局最稳:设layout为flex-column、height:100vh,页头页脚flex-shrink:0,中间区flex:1+min-height:0+overflow-y:auto,页脚天然粘底且不遮挡。

用 flex 实现三栏式垂直布局(页头+滚动区+页脚)
直接用 display: flex + flex-direction: column 是最稳的解法,浏览器兼容到 IE10+,不需要 JS 计算高度,也不依赖固定像素值。
关键在中间区域用 flex: 1 占满剩余空间,同时设 overflow-y: auto 触发滚动。页头页脚保持自然高度,不挤压内容。
- 页头和页脚用
flex-shrink: 0防止被压缩(尤其在内容少时) - 中间容器必须设
min-height: 0(Chrome/Firefox 下 flex 子项默认最小高度是内容高度,会撑开整个 viewport) - 如果页脚需要“粘底”(即内容少时也贴底),这个方案天然满足;内容多时中间区自动滚动,页脚始终在视口底部下方
.layout {
display: flex;
flex-direction: column;
height: 100vh;
}
<p>.header, .footer {
flex-shrink: 0;
}</p><p>.main {
flex: 1;
min-height: 0; /<em> 关键!否则 overflow 不生效 </em>/
overflow-y: auto;
}为什么不用 grid?
用 grid 看似更直观(比如 grid-template-rows: auto 1fr auto),但实际踩坑不少:
- IE11 对
1fr在grid中的支持有 bug,可能让中间区高度为 0 - 当页头或页脚含动态内容(如折叠菜单、响应式标题)时,
auto行高计算不稳定,容易导致滚动区被截断 - 某些安卓 WebView(尤其旧版)对
grid的1fr解析异常,比flex更难调试
除非项目明确不支持 IE/旧安卓,否则 flex 更省心。
立即学习“前端免费学习笔记(深入)”;
滚动区内容溢出时,如何避免页脚被遮挡?
常见错误是给 .main 加了 padding-bottom 或直接把页脚写在滚动区内——这会导致页脚随内容一起滚动,或者被内容盖住。
- 页脚必须是
.layout的直接子元素,和.main并列 - 不要给
.main设margin-bottom模拟页脚位置,这会破坏 flex 布局流 - 如果页脚需半透明悬浮效果,用
position: sticky+bottom: 0替代绝对定位,它仍参与 flex 布局,不会脱离文档流
移动端键盘弹起时布局错乱怎么办?
iOS Safari 和部分安卓浏览器在软键盘弹出时会错误地缩放 viewport,导致 100vh 变小,页脚上浮、滚动区变矮。
- 别依赖
100vh,改用100dvh(现代浏览器支持,Safari 16.4+、Chrome 105+) - 降级方案:用 JS 监听
resize,动态设置style.height = window.innerHeight + 'px',但注意防抖 - 更轻量的做法是加
viewportmeta:<meta name="viewport" content="height=device-height">(仅部分安卓有效)
真正麻烦的是 iOS 上 100dvh 在键盘收起瞬间有延迟,这时 flex 的弹性依然比 grid 更容错——哪怕高度短暂不准,它也会重新分配空间,不容易白屏或留大片空白。










