svh适合固定底部操作区,lvh适合全屏沉浸式内容;svh取键盘弹出时最小可用高度,lvh取浏览器UI隐藏时最大高度;二者不可混算,且不支持媒体查询和JS像素读取。

svh 适合固定底部操作区,比如输入框、TabBar、提交按钮
当页面需要一个始终可见、不被软键盘遮挡的底部区域时,100svh 是比 100vh 更安全的选择。它的值取的是“键盘弹出时的最小可用高度”,所以即使 iOS 键盘完全展开,容器也不会溢出或被截断。
- 常见翻车:用
height: 100vh包裹整个表单页,键盘弹起后 submit 按钮直接消失在视口外 - 正确做法:给表单容器设
min-height: 100svh+display: flex; flex-direction: column,再把按钮用margin-top: auto推到底部 - 注意:安卓部分 WebView(如微信 X5)不支持
svh,必须加@supports降级到100vh或 JS 补 height
lvh 适合全屏沉浸式内容,比如引导页、视频封面、游戏启动页
100lvh 对应的是“浏览器 UI 完全隐藏时的最大高度”,它基本等于设备物理屏幕高度(不含状态栏),因此更适合需要铺满整块屏幕、且不关心工具栏是否存在的场景。
- 典型误用:拿
100lvh做可滚动正文容器——键盘弹出后内容会被压缩,体验反而更差 - 推荐组合:
height: 100lvh+overflow: hidden+background-size: cover,用于首屏视觉冲击强的静态页 - 兼容性提醒:Firefox 117+ 需手动开启
layout.css.dvh-lvh-svh.enabled标志才支持,不能默认启用
别在 @media 查询里用 svh/lvh,也别指望 JS 读取它们的像素值
CSS 规范明确禁止在媒体查询条件中使用 svh 和 lvh,而且 JavaScript 通过 getComputedStyle 获取到的永远是字符串 "100svh",不是计算后的像素数,无法参与逻辑判断或动态计算。
- 错误写法:
@media (max-height: 800svh) { ... }→ 直接被忽略 - 错误写法:
el.style.height = getComputedStyle(el).height // 返回 "100svh"→ 后续无法做数值比较 - 替代方案:需要用 JS 响应视口变化时,优先监听
visualViewport的resize事件,再结合window.innerHeight差值估算键盘高度
svh 和 lvh 不是互斥关系,但不能混着算尺寸
有人试图用 calc(100lvh - 100svh) 算出键盘高度,这是错的。两者语义不同:lvh 是最大可用高度,svh 是最小可用高度,差值不等于键盘像素值,也不稳定——比如地址栏收起但键盘未弹出时,这个差值可能为 0,也可能跳变。
立即学习“前端免费学习笔记(深入)”;
- 真正需要键盘高度时,iOS 16.4+ 可用
env(keyboard-inset-bottom),但仅限 iOS - 安卓无原生等价物,JS 估算仍是主流:监听
focus后延时 100ms 读visualViewport.height变化 - 最稳妥的布局策略是:用
svh控制最小容错高度,用env(keyboard-inset-bottom)微调 bottom/padding,二者分工明确
真实项目里最容易被忽略的点,是以为加了 @supports 就万事大吉——其实很多安卓 WebView 和旧版微信内置浏览器连 @supports (height: 100svh) 都不识别,得靠 UA 判断 + 动态注入 style 标签兜底。


















