@media (orientation: landscape) 单独使用基本不可靠,必须配合正确 viewport 标签(含 width=device-width)、尺寸断点(如 min-width 或 aspect-ratio)及动态单位(dvh/dvw)才能稳定响应;其触发依赖重排且仅基于宽高比判定,易受地址栏、折叠屏等干扰,需用 window.matchMedia 动态监听并手动检查初始状态。

@media (orientation: landscape) 单独用基本不可靠,必须配 viewport 标签 + 尺寸断点 + 动态单位才能稳定响应
viewport 标签写错,orientation 媒体查询压根不触发
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">
只靠 orientation 媒体查询,横屏样式大概率延迟或漏掉
它不是实时响应旋转动作,而是在浏览器完成重排(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)—— 后者直接响应真实瓶颈(高度骤减)
flex-direction 不会自动翻转,100vh/100vw 在横屏下极易翻车
CSS 不会因为屏幕旋转就帮你把 flex-direction: column 切成 row。同样,100vh 在 iPhone 14 横屏下只剩 390px,常导致内容被截;100vw 在 iOS Safari 横屏时包含已隐藏地址栏高度,造成溢出。
立即学习“前端免费学习笔记(深入)”;
- 竖屏用
flex-direction: column,横屏媒体查询里必须显式写flex-direction: row - 优先用
100dvh和100dvw(Safari 16.4+、Chrome 105+ 支持),降级方案:min-height: 100%+html, body { height: 100% } -
font-size: 4vw横屏暴增,改用clamp(14px, 2.5vw, 16px)锁死区间 - 别混用
orientation和min-width—— 同一设备旋转时宽度不变,orientation会触发,min-width不会
JavaScript 监听别用 orientationchange,改用 matchMedia
window.addEventListener('orientationchange') 在 iOS 12+ 和所有现代安卓浏览器中已被废弃。它只反映设备陀螺仪角度,和实际 CSS 渲染方向脱节。
- 正确做法:
const mql = window.matchMedia('(orientation: landscape)') - 监听变更:
mql.addEventListener('change', e => { if (e.matches) { /* 横屏逻辑 */ } }) - 首次加载也要手动检查:
if (mql.matches) { /* 初始化横屏状态 */ } - 桌面模拟器的 “Rotate” 按钮不等价于真机旋转,测试必须用真机
真正容易被忽略的是:横屏时 gap 和 margin 的语义差异、align-items 在不同主轴下的行为变化,以及折叠屏展开后竖屏宽度超 800px 却仍被当成手机处理 —— 这些都不是 orientation 能单独解决的。


















