viewport标签缺失width=device-width会导致@media (orientation: landscape)失效;必须配对使用portrait/landscape媒体查询;orientation判定基于宽高比且有延迟,应叠加aspect-ratio等条件;100dvh比100vh更适配横屏。

viewport 标签写错,@media (orientation: landscape) 就压根不触发
绝大多数“写了但没反应”的情况,根源不在 CSS,而在 HTML 的 <meta name="viewport">。iOS Safari 和 Android Chrome 都依赖它来识别方向变化。漏掉 width=device-width,浏览器就按固定宽度渲染,@media (orientation: landscape) 永远不会匹配。
常见错误包括:
-
width=375这类固定值 —— 视口宽度锁死,旋转后媒体查询无从重算 - JS 动态覆盖初始
<meta>标签 —— 后续旋转失效 - 只写
initial-scale=1.0却缺width=device-width
推荐写法:<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
@media (orientation: portrait) 和 @media (orientation: landscape) 必须配对使用
单独写一个,另一个的样式可能被忽略或覆盖。竖屏和横屏是互斥状态,必须显式定义两套规则,否则默认样式会干扰切换逻辑。
立即学习“前端免费学习笔记(深入)”;
例如容器尺寸、flex 布局方向、定位基准等,都需成对设置:
@media (orientation: portrait) {
.container { width: 220px; height: 400px; flex-direction: column; }
}
@media (orientation: landscape) {
.container { width: 600px; height: 300px; flex-direction: row; }
}
注意:flex-direction 不会自动翻转,必须手动指定;margin 在方向切换后容易错位,优先用 gap 替代。
单独用 orientation 媒体查询大概率误判或延迟
它不是实时响应物理旋转,而是等浏览器完成 reflow 后才重新计算,通常有几十毫秒延迟。更关键的是:判定逻辑只是 if (window.innerWidth > window.innerHeight),和传感器无关。
这些场景会导致失效:
- iOS 15+ 快速旋转跳过触发
- Android Chrome v79+ 后续旋转不再更新
orientation - 横屏时地址栏未收起,
window.innerHeight仍大于宽度 - 折叠屏半展开,宽高比接近 1:1,判定摇摆
稳妥做法是叠加条件:
@media (orientation: landscape) and (min-aspect-ratio: 1280/720)-
@media (max-height: 480px) and (min-width: 640px)(直接响应高度骤减)
别混用 orientation 和 min-width 断点
同一台设备旋转时,window.innerWidth 基本不变(比如 iPad 始终是 834px),min-width: 768px 不会因方向变化而触发。真正起作用的只有 orientation。
所以 @media (min-width: 768px) and (orientation: landscape) 这种写法,实际等价于 @media (min-width: 768px) —— orientation 部分形同虚设。
如果真要兼顾设备类型和方向,应明确意图:
- 适配“小屏横屏”(如手机拍视频):
@media (orientation: landscape) and (max-width: 500px) - 适配“大屏横屏”(如 iPad):
@media (min-width: 768px) and (orientation: landscape),但此时断点意义已转向设备尺寸而非方向
最易被忽略的一点:横屏下 100vh 在 iOS Safari 中常被地址栏挤压,导致内容截断;改用 100dvh 更可靠,但要注意 Android Chrome 100 以下不支持。


















