viewport标签缺失或写错会导致orientation媒体查询完全不触发,必须包含width=device-width且置于head最顶部;推荐写法为<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">。

viewport 标签缺失或写错,orientation 就压根不计算
几乎所有 @media (orientation: landscape) 不生效的问题,根源都在 HTML 的 <meta name="viewport">。缺了、写成 width=375 这类固定值、或被 JS 动态覆盖,浏览器就根本不触发 orientation 重算。
必须包含 width=device-width——缺了它,横屏时浏览器仍按竖屏逻辑渲染,orientation 永远不匹配。
- 正确写法:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> - 错误写法:
<meta name="viewport" content="width=414">(锁死宽度,旋转后innerWidth不变) - 更隐蔽的坑:JS 执行了
document.querySelector('meta[name=viewport]').setAttribute(...),初始设置被覆盖 - 位置也很关键:该标签必须在
<head>最顶部,前面不能有注释或脚本
只写 (orientation: landscape) 为什么经常漏判或反向匹配
它只看 window.innerWidth >= window.innerHeight 这个宽高比结果,不读传感器,也不管地址栏是否收起、折叠屏是否半开。
iOS Safari 横屏时若地址栏未隐藏,innerHeight 突然变大,orientation: landscape 可能完全不匹配;Android Chrome v79+ 有时只读初始方向,后续旋转不更新。
立即学习“前端免费学习笔记(深入)”;
- 推荐叠加断点:
@media (orientation: landscape) and (min-width: 480px) - 更准的写法:
@media (orientation: landscape) and (min-aspect-ratio: 1280/720) - 桌面端别依赖它——非移动设备上始终返回
portrait - 真机测试不可替代:DevTools 的 “Rotate” 按钮 ≠ 物理旋转,iOS 快速翻转还可能跳过触发
别用 orientationchange 事件监听方向变化
window.orientation 已废弃多年,Chrome 99+ 彻底移除,Safari/Firefox 早就不响应;orientationchange 事件在现代浏览器中基本不触发,且和 CSS 渲染脱节。
正确做法是用 window.matchMedia(),它直接读取当前媒体查询匹配状态,与 CSS 同步。
- 初始化检查:
const mql = window.matchMedia('(orientation: landscape)'); - 监听变更:
mql.addEventListener('change', e => { if (e.matches) { /* 横屏 */ } else { /* 竖屏 */ } }); - 首次加载时
mql.matches就是当前状态,无需额外判断 - 避免用
resize模拟——太频繁,且无法区分是方向变化还是单纯拖拽窗口
样式没生效,可能是层叠顺序或权重问题
即使媒体查询被正确解析,样式也可能被更高优先级规则静默覆盖。常见现象:你在 Styles 面板里看到目标属性被划掉,但找不到自己写的媒体查询规则。
- 确保媒体查询块写在基础样式之后(CSS 自上而下解析,后声明者胜出)
- 同级选择器下,靠后的媒体查询才生效;若位置靠前,会被后面的基础样式覆盖
- 提升优先级的简便方式:用多级选择器,比如把
.menu改成nav .menu - 调试时可临时加
!important验证是否是权重问题,但上线前应优化选择器结构
实际项目里最常卡住的地方,不是 CSS 写错,而是 viewport 被覆盖 + 媒体查询写在基础样式前面 + 没做真机验证。这三件事不确认,光调样式没用。


















