以下是对您原文的深度润色与重构版本。我以一位资深前端工程师兼技术博主的身份,摒弃模板化表达、强化逻辑脉络、注入实战洞察,并彻底去除AI痕迹——全文读来如同一位在一线踩过无数坑的老手,在咖啡馆里边画草图边跟你聊“为什么vh在手机上总不听话”。
为什么你的100vh在 iPhone 上总是“差那么一截”?
你写了个全屏轮播页,加了height: 100vh,本地 Chrome 看着完美;一上真机,iOS Safari 打开:顶部留白、内容被切掉、滚动时整个 hero 区突然往上蹦一下……
你查控制台,document.documentElement.clientHeight是667,但屏幕明明有812像素高;你再滚两下,它又变成752—— 这不是 bug,是浏览器在“演戏”。
而这场戏的主角,就是vh:它看起来很老实,其实从没真正看过用户的眼睛。
它不是“屏幕高度”,而是“浏览器给你的快照”
很多人以为1vh = 屏幕高度的 1%,错。1vh = 当前布局视口(layout viewport)高度的 1%—— 而这个“布局视口”,压根儿不是你手指划过的那块玻璃,而是浏览器悄悄给你画的一张“施工图纸”。
这张图纸有多大?取决于两件事:
- 你
<meta>里写的initial-scale和width; - 更关键的是:Safari 地址栏有没有收起来。
✅ 加载完成瞬间:地址栏展开 → 布局视口被砍掉约
90px(状态栏 + URL 栏)→100vh ≈ 630px
✅ 向下滑动后:地址栏自动收起 → 布局视口“啪”地变高 →100vh突然跳到720px
✅ 此时所有height: 100vh的元素同步拉伸 → 页面像被拽了一把,内容上浮、“跳帧感”扑面而来
这不是 CSS 不够聪明,是它压根儿没被设计成“盯梢员”。vh在样式计算阶段就定死了值,之后不管视觉视口怎么变,它都纹丝不动——直到你触发一次重排(比如改 class、动 transform、甚至只是offse