viewport标签必须含width=device-width,否则@media(orientation:landscape)不触发;该查询仅在重排后延迟生效且依赖逻辑宽高比,需结合min-aspect-ratio或max-height等条件增强判断。

viewport 标签写错,@media (orientation: landscape) 压根不触发
iOS Safari 和 Android Chrome 都依赖 <meta name="viewport"> 判断方向变化。漏掉 width=device-width,浏览器就按固定宽度渲染,@media (orientation: landscape) 永远不匹配。
常见错误:width=375 这类固定值 —— 视口宽度不变,媒体查询无从重算。
更隐蔽的问题:JS 动态覆盖了初始 <meta> 标签,后续旋转失效。
推荐写法:<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
立即学习“前端免费学习笔记(深入)”;
@media (orientation: landscape) 单独用基本不可靠
它不是实时响应旋转动作,而是在浏览器完成重排(reflow)后才重新计算,通常有几十毫秒延迟。更关键的是:它只看“逻辑宽度是否大于高度”,不关心物理朝向或 UI 栏是否展开。
iOS 15+ 快速旋转可能跳过触发;Android Chrome v79+ 仅读取初始方向,后续旋转不再更新。
横屏时若地址栏未收起、折叠屏半展开,window.innerWidth <= window.innerHeight,orientation: landscape 可能根本不匹配。
稳妥做法是组合判断:
@media (orientation: landscape) and (min-aspect-ratio: 1280/720)-
@media (max-height: 480px) and (min-width: 640px)—— 后者直接响应真实瓶颈(高度骤减)
横屏下 100vh 和 flex-direction 不会自动翻转
CSS 不会因为屏幕旋转就帮你把 flex-direction: column 切成 row。同样,100vh 在 iPhone 14 横屏下只剩 390px,常导致内容被截;100vw 在 iOS Safari 横屏时包含已隐藏地址栏高度,造成溢出。
实操建议:
- 避免用
height: 100vh做容器主高,改用height: 100dvh(dynamic viewport height),它自动排除 UI 栏;但注意 Android Chrome 100 以下不支持 - 若需兼容老环境,用
height: 100%+ 父级display: flex; flex-direction: column控制伸缩 - 文字行高、内边距等非结构性尺寸,优先用
rem或em,而非vh
别混用 orientation 和 min-width —— 同一设备旋转时宽度不变
很多开发者写 @media (min-width: 768px) and (orientation: landscape) 本意是适配平板横屏,但没意识到:同一台 iPad 旋转时,window.innerWidth 基本不变(比如始终是 834px),min-width 不会随方向变化而触发,真正起作用的只有 orientation。
所以,如果只靠 min-width 判断“是不是平板”,容易误判:小尺寸安卓平板横屏时 viewport 宽度可能仍是 600px 左右,因为系统 UI 或浏览器缩放干扰了实际值。
更实用的做法:
- 基础层用
@media (min-width: 768px)做“有横屏能力”的粗筛 - 增强层用
@media (min-aspect-ratio: 16/9)或@media (max-height: 500px)补充验证 - 字体字号改用
clamp(14px, 2.5vw, 16px)锁死区间,避免横屏时4vw暴增
最易被忽略的点:首次加载必须手动检查 matchMedia('(orientation: landscape)').matches,否则页面刚打开时横屏状态不会生效 —— 媒体查询不会回溯历史,只响应变化。


















