必须配对才能触发@media (orientation: ...),否则样式不切换;需含width=device-width,推荐写法为。

必须配对 <meta name="viewport"> 才能触发 @media (orientation: ...),否则样式压根不会切换。
viewport meta 标签写错,orientation 媒体查询就失效
很多页面写了 @media (orientation: landscape) 却没反应,不是 CSS 写错了,而是 HTML 里缺了或写错了 <meta name="viewport">。iOS Safari 和 Android Chrome 都依赖这个标签来识别方向变化。
- 必须包含
width=device-width—— 缺了它,横屏时浏览器仍按竖屏逻辑渲染,orientation永远不匹配 - 禁用固定值,比如
width=375或width=414,否则横屏时视口宽度没变,媒体查询不会重算 - 推荐写法:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">(user-scalable=no能减少安卓 WebView 中因缩放导致的方向误判)
@media (orientation: landscape) 的触发时机很“懒”
这个媒体查询不是一旋转就立刻生效,而是在浏览器完成重排(reflow)后才重新计算,通常有几十毫秒延迟。更关键的是:它只看“逻辑宽度是否大于高度”,不看物理朝向。
- 横屏时如果
window.innerWidth (比如地址栏未隐藏、折叠屏半展开),<code>orientation: landscape可能根本不匹配 - 稳妥做法是叠加宽高比判断:
@media (orientation: landscape) and (min-aspect-ratio: 1280/720) - 不要用
@media (max-width: 768px)替代orientation—— 分屏模式、折叠屏展开时会误触发
JavaScript 监听不能靠 orientationchange 事件
window.addEventListener('orientationchange', ...) 在 iOS 12+ 和所有现代安卓浏览器中已被废弃。它只读陀螺仪角度,和实际渲染方向脱节(比如 App 强制竖屏,事件照发但 CSS 不变)。
立即学习“前端免费学习笔记(深入)”;
- 正确方式是用
window.matchMedia('(orientation: landscape)') - 监听变更:
mql.addEventListener('change', e => { if (e.matches) { /* 横屏逻辑 */ } }) - 首次加载必须手动检查:
if (mql.matches) { /* 初始化横屏状态 */ },否则直出横屏页面会跳过初始样式 - 注意:
screen.orientation.type在 iframe 中可能被Permissions-Policy禁用
100vw 在横屏下容易切掉内容,别直接用
iOS Safari 横屏时 100vw 会包含已隐藏的地址栏高度(即使设置了 user-scalable=no),导致实际可渲染宽度变小,内容溢出或错位。
- 优先改用
width: 100%+ 父容器overflow-x: hidden - 如需视口单位,用
100dvw(dynamic viewport width),它自动排除 UI 栏;但注意 Android Chrome 100 以下不支持 - 测试务必真机操作:模拟器和 Safari 开发者工具的“旋转”按钮不模拟地址栏高度变化
最常被忽略的一点:横竖屏样式冲突往往不是媒体查询失效,而是其他规则覆盖了它——比如内联样式、更高优先级的选择器、或 !important 没加在对应媒体查询块里。


















