错位是100vh/100vw基准突变、orientation媒体查询未生效及viewport标签缺失三者叠加所致;须优先确保viewport正确,再用@media (orientation: landscape)显式重置尺寸,禁用user-scalable=no,改用100dvh/dvw或min-height:100%兜底。

直接结论:错位不是 CSS 写错了,而是 100vh/100vw 基准突变 + orientation 媒体查询未生效 + viewport 标签缺失三者叠加的结果;优先检查 <meta name="viewport"> 是否正确,再用 @media (orientation: landscape) 显式重置关键尺寸,别依赖 vh。
viewport 标签写错,@media (orientation: landscape) 根本不会触发
iOS Safari 和 Android Chrome 都靠这个标签识别方向变化。漏掉 width=device-width,横屏时浏览器仍按竖屏逻辑渲染,orientation 永远不匹配。
- 必须写:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> - 禁用
maximum-scale=1或user-scalable=no组合——它会让dvh、visualViewport全部失效 - 别写死
width=375,真机会忽略该值,导致媒体查询无法重算 - JS 动态覆盖过 viewport?初始设置后又被改写,后续旋转就彻底失联
@media (orientation: landscape) 单独用大概率延迟或漏掉
它不是实时响应旋转动作,而是在浏览器完成重排(reflow)后才重新计算,通常有几十毫秒延迟。更关键的是:它只看“逻辑宽度是否大于高度”,不关心物理朝向或 UI 栏是否展开。
- iOS 15+ 快速旋转可能跳过触发;Android Chrome v79+ 仅读取初始方向,后续旋转不再更新
- 推荐组合判断:
@media (orientation: landscape) and (min-height: 400px)或@media (max-height: 480px) and (min-width: 640px)——后者直接响应真实瓶颈(高度骤减) - 绝对定位元素如
top: calc(100vh - 60px)在横屏下会算出极小值,直接贴顶;应改用bottom: env(safe-area-inset-bottom)或显式设top: 10px - 首次加载必须手动检查当前状态:
const mql = window.matchMedia("(orientation: landscape)"); handleOrientation(mql.matches);
100vh / 100vw 在横竖屏下基准突变,必须兜底
iPhone 14 竖屏 100vh ≈ 844px,横屏只剩 390px;iOS Safari 的 100vw 还包含已隐藏地址栏高度,造成溢出。这不是 bug,是浏览器行为。
- 改用
100dvh(动态视口高度)和100dvw(现代 Safari / Chrome 支持,但 Android WebView 旧版本不认) - 稳妥降级方案:
min-height: 100%;+html, body { height: 100%; }+overflow-y: auto -
font-size: 4vw横屏暴增 → 改用clamp(14px, 2.5vw, 16px)锁死区间 - 滚动容器右侧出现空白?加
overflow-gutter: stable,fallback 用padding-right: calc(100vw - 100%)动态补偿(别写死17px)
真机测试时最容易忽略的三个隐性偏差
模拟器看不出问题,但真机会暴露:
-
flex-basis在 iOS Safari 和 Android WebView 中解析不一致:有的转成auto,有的保留像素值——务必在真机上检查 computed 样式 -
visualViewport.height在键盘收起瞬间有几十毫秒延迟,直接读可能拿到旧值,必须加setTimeout(() => {}, 50)防抖 - 第三方 UI 库(如 Vant)内部用了
position: absolute或transform,会脱离 flex 流,display: flow-root也救不了——得单独重写该组件的定位逻辑
复杂点在于:错位从来不是单一原因,而是 viewport 缺失、margin 合并、100vh 锁定、滚动条占宽、flex-shrink 默认压缩等规范行为同时生效。修复顺序必须是:先保 viewport 正确,再用 orientation 媒体查询接管布局主干,最后用 JS 补动态细节——任何跳步都会让问题反复出现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











