@media (orientation: landscape) 和 @media (orientation: portrait) 需配合正确 viewport 设置(如 width=device-width)才能生效,其判断基于宽高比而非物理方向,存在误判可能,纯样式调整优先用 CSS,交互逻辑应使用 matchMedia 监听。

@media (orientation: landscape) 和 @media (orientation: portrait) 是 CSS 媒体查询中用于响应横竖屏切换的原生方式,但它们不是独立生效的魔法开关——必须配合正确的 viewport 设置、理解其判断逻辑,并知道何时该补上 JavaScript 才可靠。
viewport 是前提,缺了它整个 orientation 查询就失效
orientation 媒体查询只在浏览器正确识别视口尺寸变化时才触发。如果 <meta name="viewport"> 写错或缺失,样式根本不会匹配,连调试都找不到原因。
- 必须包含
width=device-width:缺了它,横屏时浏览器仍按竖屏逻辑渲染,orientation: landscape永远不成立 - 禁用固定宽度(如
width=414):否则横屏时视口宽度没变,媒体查询无从触发 - 推荐写法:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
iOS Safari、Android Chrome、PWA 和部分 iframe 场景都依赖这个标签识别方向变化;若被 JS 动态覆盖(比如某些 H5 框架重写 viewport),也会导致失效。
orientation 只看宽高比,不读传感器
它判断的是 window.innerWidth >= window.innerHeight,和设备物理朝向无关:
立即学习“前端免费学习笔记(深入)”;
- 地址栏未隐藏(尤其 iOS Safari):横屏时
innerHeight突然变大,可能让landscape不匹配 - 折叠屏半展开、分屏模式(Slide Over)、桌面端拖拽窗口:宽高比“凑巧”满足或不满足,造成误判
- 它不实时触发:只在浏览器完成 reflow 后延迟生效(几十毫秒),不是一转就切
所以别指望它 100% 精准。稳妥做法是叠加条件:
@media (orientation: landscape) and (min-width: 480px) { ... }
/* 或更准的 */
@media (min-aspect-ratio: 1280/720) { ... }纯样式调整,优先用 CSS 媒体查询
如果只是隐藏元素、改 flex 方向、调字体大小、换布局结构,完全不需要 JS:
.form-row { display: block; }
@media (orientation: landscape) {
.form-row { display: flex; gap: 16px; }
.input-full { flex: 1; }
}好处是:
- 渲染稳定,无白屏或闪动风险
- 支持服务端渲染(SSR)
- 性能轻量,不占主线程
但注意:它无法触发 DOM 操作(比如显示提示层、上报埋点、暂停视频),这类逻辑必须交给 JS。
需要交互响应?用 matchMedia 而不是 orientationchange
window.addEventListener('orientationchange') 已废弃多年,iOS 12+ 和现代安卓浏览器基本不触发,且和实际视口方向脱节。
推荐写法:
const mql = window.matchMedia('(orientation: landscape)');
mql.addEventListener('change', e => {
if (e.matches) {
document.body.classList.add('is-landscape');
} else {
document.body.classList.remove('is-landscape');
}
});
// 首次调用 matches 就是当前状态,无需额外判断
if (mql.matches) {
document.body.classList.add('is-landscape');
}兼容性好(Chrome 38+、Firefox 32+、Safari 9+、Edge 12+),语义清晰,性能轻量,且不依赖陀螺仪。
不复杂但容易忽略



















