直接写 height: 100vh 在 iOS Safari 中漏掉底部,是因为其按初始布局视口(含地址栏)静态计算 100vh,滚动后地址栏收起、可视区域变大,但 100vh 值不更新,导致容器高度小于实际可用空间;应改用 min-height: 100dvh 并配合 @supports 降级,旧环境需 JS 动态设 --vh 变量。

为什么直接写 height: 100vh 在 iOS Safari 里会漏掉底部
不是代码写错了,是浏览器把地址栏高度静态计入了视口计算。iOS Safari(尤其是 15+)在页面加载时用初始视口高算出 100vh,但滚动后地址栏收起,实际可用空间变大,而 100vh 值不变,结果就是容器“撑不满”,底部被截或出现意外滚动条。
这不是 bug,是设计行为;但对全屏布局来说,它直接破坏体验。
- 优先用
min-height: 100dvh(动态视口单位),iOS 16+/Chrome 105+ 已支持,能实时响应地址栏显隐 - 降级必须加 JS:监听
resize和visualViewport变化,动态设置--vh变量,再用height: calc(var(--vh, 1vh) * 100) - 绝对不要给
html或body设height: 100vh—— 容易触发 iOS 缩放异常和输入框聚焦后的滚动错位
盒模型怎么防止 padding 或 border 撑破全屏尺寸
即使 100dvh 算对了,padding: 20px + border: 2px 也会让元素总高变成 100dvh + 44px,溢出滚动。这是默认 box-sizing: content-box 的必然结果。
- 全局重置:
* { box-sizing: border-box; }或至少作用于:root,让padding和border包含在设定高度内 - 全屏容器必须显式清空外边距:
margin: 0,并加overflow: hidden防止子内容意外溢出 - 避免用
padding-bottom: 20px模拟安全区留白——它会吃掉内容空间;改用padding-bottom: env(safe-area-inset-bottom)并配<meta name="viewport" content="viewport-fit=cover">
全屏容器里图片铺满又不变形,object-fit 怎么选
没有“完整铺满且 100% 不变形”的方案,本质是裁剪还是留白的选择问题。关键看容器是否固定宽高、是否允许内容被切掉。
立即学习“前端免费学习笔记(深入)”;
- 要填满无空白(如 Banner、卡片图):用
object-fit: cover+object-position: center,配合overflow: hidden - 要全部可见不裁剪(如证件照、图表):用
object-fit: contain,但需接受上下/左右留白,或用flex: 1+align-items: center居中 - 若容器本身宽高不确定,优先用背景图:
background-size: cover+background-position: center,比<img>更可控
键盘弹出时全屏布局塌陷,怎么稳住
iOS 键盘弹出会大幅压缩可视区域,100dvh 虽然动态,但变化滞后且幅度不准;单纯靠 CSS 很难兜底。
- 检测键盘状态:监听
visualViewport的height变化,当它明显小于屏幕高(比如 - 临时切换布局策略:把全屏容器设为
flex: 1,内部内容用overflow-y: auto,保证可滚动而非被压扁 - 慎用
position: fixed全屏遮罩——键盘弹出时可能被顶出视口,改用position: absolute+inset: 0更可靠
全屏布局最难的从来不是“怎么写满”,而是“怎么在地址栏收放、键盘进出、安全区变化这些真实交互中始终不破形”。100dvh 是起点,box-sizing: border-box 是底线,而 visualViewport 监听才是应对复杂场景的真正开关。


















