@media (orientation: landscape/portrait) 依赖正确的 viewport 设置才能生效,缺 width=device-width 或被 JS 覆盖会导致媒体查询完全失效;它仅基于宽高比判断,不读传感器,且受地址栏、折叠屏、分屏等影响,推荐用 window.matchMedia 监听并验证 matches 值。

@media (orientation: landscape) 和 @media (orientation: portrait) 能用,但必须配对正确的 才生效;否则样式压根不会匹配,连调试都找不到原因。
viewport 标签写错,orientation 媒体查询就完全失效
几乎所有“写了样式却没反应”的问题,根源都在 HTML 的 。缺了、写成 width=375 这类固定值、或被 JS 动态覆盖,@media (orientation: landscape) 就不会重新计算。
- 必须包含
width=device-width——缺了它,横屏时浏览器仍按竖屏逻辑渲染,orientation永远不匹配 - 禁用固定宽度(如
width=414),否则横屏时视口宽度没变,媒体查询无从触发 - 推荐写法:
- iOS Safari 和 Android Chrome 都依赖这个标签识别方向变化;PWA 或 iframe 嵌入时还可能受
Permissions-Policy限制
@media (orientation: landscape) 只看宽高比,不读传感器
它只判断 window.innerWidth >= window.innerHeight,不读陀螺仪、不看物理朝向。很多场景下会漏判或误判:
- 地址栏未隐藏(尤其 iOS Safari),导致横屏时
innerHeight突然变大,orientation: landscape不匹配 - 折叠屏半展开、分屏模式(Slide Over)、桌面端手动拉宽窗口,都会让宽高比“凑巧”满足或不满足
- 它不实时监听,只在浏览器完成 reflow 后延迟生效(几十毫秒),不是一转就切
- 稳妥做法是叠加条件:
@media (orientation: landscape) and (min-width: 480px),或更准的@media (min-aspect-ratio: 1280/720)
window.matchMedia() 是唯一可靠的 JS 监听方式
window.addEventListener('orientationchange', ...) 已废弃多年,iOS 12+ 和所有现代安卓浏览器都不再保证其与 CSS 渲染同步。它只读传感器角度,和实际视口方向脱节。
- 正确做法:
const mql = window.matchMedia('(orientation: landscape)'); - 监听变更:
mql.addEventListener('change', e => { if (e.matches) { /* 横屏 */ } else { /* 竖屏 */ } }); - 注意:首次调用
mql.matches就是当前状态,无需额外判断 - 不要用
resize事件模拟——它太频繁,且无法区分是方向变化还是单纯拖拽窗口
真正复杂的地方在于:横竖屏判断从来不是纯技术问题,而是 viewport 设置、浏览器行为、系统 UI(如地址栏高度)、设备形态(折叠屏/分屏)共同作用的结果。最常被忽略的,是没验证 matchMedia 返回的 matches 值是否与实际视觉一致——尤其在 iOS 上,地址栏收放会悄悄改掉 innerHeight,让“横屏”判定失效。动手前先 console.log 两秒,比硬写逻辑管用得多。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











