最稳妥做法是将body设为flex容器并设min-height:100vh,main用flex:1占剩余空间,header/footer保持流内尺寸;IE11兼容可改用margin-top:auto于footer;grid方案用grid-template-rows:auto 1fr auto更语义化。

flex布局让header/main/footer自然撑满视口
最稳妥的做法是把 body 设为 flex 容器,main 用 flex: 1 吃掉剩余空间,header 和 footer 保持流内尺寸。这样既避免遮挡,又不用手动算高度。
-
body必须设min-height: 100vh(不是height: 100vh),否则短内容页会被拉伸溢出 -
main必须写flex: 1,否则footer会卡在main下方,不“沉底” -
header和footer不要加position,它们的高度会自动被main尊重 - IE11 对
flex: 1支持不稳,如需兼容,可改用margin-top: auto加在footer上
grid布局用grid-template-rows: auto 1fr auto
Grid 方案更语义化,代码更少,现代浏览器支持良好,iOS Safari 14.5+ 也无 vh 跳变问题。
-
body必须显式设min-height: 100vh,否则 grid 不会按视口高度计算 -
footer默认不会拉伸宽度,加justify-self: stretch可确保它铺满整行 - 不用管
header/footer高度是否固定——auto行高会自适应内容 - 如果页面有多个
footer或嵌套结构,注意grid只作用于直接子元素
别轻易用position: fixed固定头尾
position: fixed 看似简单,但实际埋了多个运行时隐患:遮挡内容、滚动错位、移动端视口高度跳变(尤其 Safari)、响应式适配成本高。
- 必须给
main加margin-top和margin-bottom手动预留空间,否则内容会被盖住 - 需要显式设置
z-index,且得保证头尾层级高于内容,否则点击事件可能失效 - 在 iOS 上,
fixed元素常因键盘弹出或地址栏收起导致位置偏移 - 若用
calc(100vh - 头高 - 尾高)控制main高度,遇到动态内容或字体加载延迟时容易计算错误
移动端要注意的几个细节
移动端不是桌面的缩小版,很多看似“能跑”的布局在真机上会出问题。
立即学习“前端免费学习笔记(深入)”;
- 不要依赖
height: 100vh做全屏计算——Safari 在地址栏收起/展开时会触发视口高度跳变 - 如果要用
position: sticky做粘性头部,确保父容器没有overflow、transform或filter,否则 sticky 失效 - 滚动区域必须设
overflow-y: auto且-webkit-overflow-scrolling: touch(iOS 旧版本仍需) - 测试时务必在真机上验证:横竖屏切换、键盘弹出、深色模式切换都会影响布局表现
实际落地时,flex 和 grid 的差异往往不在功能,而在维护成本——前者对开发者心智负担小,后者对复杂二维结构更清晰。真正容易被忽略的是:所有方案都依赖 min-height: 100vh 这个前提,而这个前提在嵌入 iframe 或 PWA 场景下可能被父级样式覆盖。



















