svh/lvh 与 vh 语义不同:100svh 是 UI 全显时最小高度,100lvh 是 UI 隐藏时最大高度,100vh 是初始静态高度;混用导致布局错乱,需按场景精准选用并配合 @supports 检测和 JS 回退。

svh/lvh 不能直接当 100vh 用,语义完全不同
看到 100svh 就以为是“更小的 100vh”,这是最常踩的坑。它们不是大小关系,而是三种独立状态下的高度基准:100svh 是浏览器 UI(地址栏、工具栏)强制显示时的最小可用高度;100lvh 是 UI 强制隐藏时的最大高度;而 100vh 是初始加载那一刻的静态高度,不响应任何变化。
混用会出问题。比如给一个全屏轮播容器设 height: 100dvh,同时又给底部按钮加 margin-bottom: 5svh,两个单位基准不同——前者随滚动实时变,后者始终锚定在最小视口,结果就是按钮位置飘忽不定。
典型误用场景:
- 用
100svh做全屏页容器:太保守,页面永远按“地址栏全显”来算,顶部大量留白 - 用
100lvh做输入框父容器:键盘弹出时高度不收缩,内容被盖住 - 在
@media查询里写svh:CSS 规范明确禁止,解析直接失败
哪些场景该用 svh,哪些必须用 lvh
100svh 的核心价值是「保底可见」——它确保元素在最不利条件下(UI 全开 + 键盘弹出)也不被遮挡。适合支付确认页、弹窗操作区、底部固定按钮等关键交互区域。
立即学习“前端免费学习笔记(深入)”;
100lvh 则追求「最大可用空间」,适合对沉浸感要求高、且能容忍滚动初期被地址栏短暂遮挡的场景,比如全屏视频、Canvas 绘图、AR 页面背景。
常见搭配:
- 支付页底部按钮:
height: 12svh+position: fixed; bottom: 0; - 全屏视频容器:
min-height: 100lvh+object-fit: cover - 表单页主内容区:
max-height: 85svh+overflow-y: auto,保证键盘弹出后仍有可滚动空间
@supports 检测必须精确,微信 WebView 需 JS fallback
直接写 min-height: 100svh 在 iOS 15、微信内置 WebView(截至 2026 年 5 月)、QQ 浏览器里会完全失效——这些环境不认识 svh,整条 CSS 声明被丢弃,退回到无高度控制状态。
正确检测方式只有一种:@supports (min-height: 100svh) 或 @supports (min-height: 100lvh)。注意:
- 不能写成
@supports (height: 100svh):因为height属性不支持svh/lvh,只支持min-height/max-height - 不能写成
@supports (svh: 1px):语法非法,浏览器直接忽略 - 微信环境必须 JS 补偿:监听
focusin/focusout和resize,动态设style.minHeight = window.innerHeight + 'px'
Flex 居中失败?大概率是容器没真正撑开
写了 display: flex; justify-content: center; align-items: center 却不居中,90% 的原因是父容器没获得有效高度。Flex 的 align-items: center 依赖容器有明确的块级高度,而 min-height: 100svh 或 100lvh 本身不触发父级高度继承链。
必须同时满足:
html, body { margin: 0; padding: 0; height: 100%; }- 目标容器设
min-height: 100svh(或100lvh)+display: flex - 全局加
* { box-sizing: border-box; },避免 padding/border 撑破计算
特别注意:iOS Safari 中,仅靠 min-height: 100svh 不足以触发 Flex 居中,必须配合 height: 100% 向上透传,否则子元素的 100% 会按 0 计算。



















