最稳妥方式是用flex或grid布局:body设min-height:100vh和display:flex/column或display:grid/rows:auto 1fr auto,main用flex:1或1fr自适应,header/footer保持流内尺寸,避免position:fixed导致的遮挡、跳变与维护问题。

固定头部和底部最稳妥的方式是用 display: flex 或 display: grid,而不是靠 position: fixed 硬顶——后者容易遮挡内容、滚动错位、移动端视口高度跳变,且响应式适配成本高。
用 Flex 布局让 header/main/footer 自然撑满视口
核心是把 body 变成 flex 容器,main 用 flex: 1 吃掉剩余空间,header 和 footer 保持自然流内尺寸。
-
body必须设min-height: 100vh(不是height: 100vh),否则短内容页会被拉伸溢出 -
main必须写flex: 1(等价于flex-grow: 1),否则 footer 会粘在 main 下方,不“沉底” - IE11 对
flex: 1支持不稳,如需兼容,可改用margin-top: auto加在footer上 - header 和 footer 不要设
position,它们的高度会自动被main尊重
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
header, footer {
flex-shrink: 0; /* 防止被压缩 */
}
main {
flex: 1;
overflow-y: auto;
}
用 Grid 一行定义三行轨道,更语义化
Grid 方案代码更少、结构更干净,现代浏览器支持良好,iOS Safari 14.5+ 也无 vh 跳变问题。
-
grid-template-rows: auto 1fr auto中的1fr表示中间区域占满所有剩余空间 -
body必须显式设min-height: 100vh,否则 grid 不会按视口高度计算 - footer 默认不会拉伸宽度,加
justify-self: stretch可确保它铺满整行 - 不用管 header/footer 高度是否固定——
auto行高会自适应内容
body {
display: grid;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
margin: 0;
}
footer {
justify-self: stretch;
}
为什么别轻易用 position: fixed
fixed 看似简单,但实际埋了多个运行时隐患:
- header 和 footer 脱离文档流,
.main-content必须手动加margin-top和margin-bottom,值必须严格匹配它们的实际高度 - 移动端地址栏收起/展开时,
100vh会动态变化,导致calc(100vh - 60px - 40px)计算失准,内容区突然变高或变矮 - 如果 header 高度响应式(比如折叠菜单),
margin-top得靠媒体查询或 JS 同步,维护成本陡增 -
z-index只控制层叠,不解决布局遮挡;漏设margin或高度算错,内容就直接被盖住
绝对定位 + padding-bottom 是最后兜底方案
当项目已用老旧框架(比如 jQuery UI 套件)、无法改动整体布局结构时,可用此法绕过 flex/grid 依赖。
- 给
body设position: relative,作为 footer 的定位参考 - footer 设
position: absolute; bottom: 0,并显式写死height - 给
main或body加padding-bottom(值 ≥ footer 高度),防止内容被遮 - 缺点明显:中间区域不会自适应填满视口;若内容少,页面下半截就是大片空白
真正要注意的不是“怎么写出来”,而是 header 和 footer 的高度是否可预测、是否随设备或状态变化——只要这个不确定,任何基于固定数值的 margin/padding/calc 都会变成定时炸弹。Flex 和 Grid 的优势,正在于它们根本不依赖你去猜高度。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











