vw/vh是视口宽度/高度的1%,始终以viewport为基准,不同于%依赖父元素;因滚动条和safari地址栏变化会导致布局异常,故不可无脑替代%;vmin/vmax分别取vw/vh中较小/较大值,适用于横竖屏一致缩放,如全屏容器、响应式字体、svg等。

vw/vh 是什么,为什么不能直接当“百分比”用
vw 和 vh 分别代表视口宽度和高度的 1%,比如 50vw 就是当前浏览器窗口宽度的一半。但它们和 % 的行为本质不同:% 是相对于父容器计算的,而 vw/vh 始终以整个视口为基准——哪怕元素被嵌套在层层 div 里,也不会受父级尺寸影响。
这带来两个典型问题:
- 页面有横向滚动条时,
100vw会包含滚动条宽度(Chrome/Firefox 下通常多出 ~17px),导致内容溢出或布局错位 - 在移动端 Safari 中,地址栏收起/展开会动态改变
vh值,造成元素突然缩放或跳动
所以别无脑替换 width: 100% → width: 100vw,得看场景。
什么时候该用 vmin 和 vmax
vmin 取视口宽高中的较小值,vmax 取较大值。它们真正有用的地方,是做等比缩放容器或响应式文字,尤其在横竖屏切换频繁的设备上。
常见适用场景:
- 全屏轮播图容器,要求始终填满可视区域且不裁切 → 用
min-width: 100vmin; min-height: 100vmin;配合object-fit: cover - 标题字号随屏幕变小而线性缩小,避免小屏上文字撑破布局 →
font-size: 5vmin;(比媒体查询更平滑) - SVG 图标需要随视口等比缩放,又不想写 JS 监听 resize → 直接设
width: 20vmax; height: auto;
注意:vmin/vmax 在旧版 iOS Safari(font-size: clamp(1.2rem, 5vmin, 2.5rem);
vh 在移动端的实际坑与绕过方法
最常踩的坑是:在 iOS Safari 中,初始加载时 100vh 按地址栏未收起状态计算,用户滚动后地址栏隐藏,vh 实际变大,导致底部留白或内容上移。
解决思路不是放弃 vh,而是绕开它的动态性:
- 用 JS 获取一次初始
window.innerHeight,然后设为 CSS 自定义属性:document.documentElement.style.setProperty('--vh', <code>${window.innerHeight * 0.01}px);,后续用height: calc(var(--vh) * 100); - 或者改用
dvh(dynamic viewport height):现代 Safari(iOS 16.4+)、Chrome 109+ 已支持,它会自动响应地址栏变化,100dvh始终等于当前可见区域高度 - 如果只做简单全屏占位,且允许轻微错位,可加
min-height: 100vh; height: 100dvh;双保险
别忘了测试真机——模拟器往往不触发地址栏收起逻辑,vh 表现和真实环境差异很大。
性能和可访问性隐含代价
vw/vh 单位本身不触发重排,但滥用会导致意料之外的渲染压力:
- 大量元素使用
font-size: 2.5vmax,视口缩放时字体频繁重绘,低端安卓机可能卡顿 -
vmin/vmax在 resize 过程中持续重新计算,若配合will-change: transform或复杂阴影,GPU 内存占用会上升 - 屏幕阅读器不会因
vw改变而调整文字语义,但过小的0.8vmin字号可能低于可读下限(WCAG 建议最小 16px)
真正难的不是写对单位,而是判断某个尺寸是否「必须」随视口变化——很多时候固定值 + 媒体查询更可控,也更容易做无障碍适配。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











