主内容区不能直接写height: 100vh,因其等于整个视口高度,未扣除头部、侧边栏等固定元素占用空间,易导致遮挡、留白或滚动错位;且在safari/ios地址栏收放时会动态跳变,旧浏览器也不支持100dvh需降级。

主内容区高度为什么不能直接写 height: 100vh
写了 height: 100vh 后,内容区常被头部遮挡、底部留白、或滚动条出现在 body 上——根本原因是 100vh 是整个视口高度,没扣除固定定位的头部和侧边栏所占空间。尤其在 Safari 或 iOS 设备上,地址栏收放还会导致 vh 动态变化,造成布局跳变。
更隐蔽的问题是:如果父容器(比如 .layout)没设 height,子元素的 height: 100% 会计算为 0,因为百分比高度必须有明确的父级高度参照。
- 必须先确保
html,body有显式高度:html, body { height: 100%; margin: 0; padding: 0; } - 若用
100dvh(推荐),需加 fallback:height: 100dvh; height: 100vh;,因部分旧浏览器不支持dvh -
100dvh能规避 iOS 地址栏收缩导致的高度抖动,截至 2026 年主流浏览器均已支持
用 calc() 扣除固定组件高度时,怎么避免数值错位
常见写法如 height: calc(100vh - 48px - 60px) 看似合理,但一旦头部或侧边栏实际高度因 box-sizing: border-box、padding 或字体渲染差异而改变,就会出错。浏览器开发者工具里看 computed height 才是真实值,不能靠代码里写的“大概 48px”去猜。
- 头部高度必须取真实渲染值:用
getBoundingClientRect().height或 DevTools 的 Computed 面板确认 - 如果头部用了
border-bottom或box-shadow,这些不计入height,但会影响视觉对齐,建议统一用padding-bottom替代 - 侧边栏若也 fixed,它的
top必须等于头部真实高度,否则会覆盖或错位 - 不要在 CSS 里硬写多个
calc()嵌套,如calc(calc(100vh - 48px) - 60px),可读性差且无必要
Flex 布局下主内容区如何真正“撑满剩余空间”
很多人给容器设 display: flex; flex-direction: column,再给内容区加 flex: 1,却发现它没填满——问题往往出在父容器没设高度,或子项写了 align-self: flex-start 主动放弃拉伸。
- 父容器必须有明确高度来源,例如:
height: 100dvh或min-height: 100dvh - 内容区需同时满足:
flex: 1+min-height: 0(防止内部 flex 子项溢出时撑破容器) - 避免给内容区设
height: 100%,它和flex: 1冲突,后者优先级更高 - 若内容区内部是表格或 grid,记得它们默认不继承父级高度,需额外设
height: 100%或min-height: 0
滚动失效或双滚动条的根本原因和修复点
最典型现象:内容区内容超长,但只看到 body 滚动条,侧边栏跟着动;或者内容被裁剪,一点都滚不动。这不是 JS 逻辑问题,而是 CSS 层级关系没理清。
- 侧边栏用
position: fixed时,内容区必须设overflow-y: auto,且不能依赖 body 滚动 - 内容区若设了
height: calc(100vh - 48px),又加overflow-y: auto,就只会在该区域内滚动——这是正确行为 - 如果还看到外层 body 滚动条,说明某个祖先元素(比如
html或body)漏了overflow: hidden - Safari 对
overflow: auto在 flex 子项中的处理更严格,务必加min-height: 0防止高度计算异常
实际最难把控的,是头部和侧边栏高度在不同设备、不同缩放比例、不同字体渲染下的微小偏差——它们看起来只差 1–2px,却足以让 calc() 失效或触发滚动条错位。与其反复调像素值,不如用 100dvh + Flex + min-height: 0 这套组合,在绝大多数现代场景下更鲁棒。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











