@media (orientation: landscape) 不触发的根本原因是 viewport 标签错误,必须含 width=device-width 才启动方向重算;它仅依宽高比判定、有 reflow 延迟,且易受地址栏、折叠屏干扰,需配合 window.matchmedia 动态监听与 dvh/dvw 单位确保准确响应。

viewport 标签写错,@media (orientation: landscape) 就不触发
它根本不是 CSS 本身的问题,而是浏览器压根不进入方向重算流程。iOS Safari 和 Android Chrome 都依赖 <meta name="viewport"> 中的 width=device-width 来识别视口是否随旋转变化。
常见错误包括:
- 漏写
width=device-width—— 横屏时仍按竖屏宽度渲染,orientation永远不匹配 - 写成固定值如
width=375—— 视口宽度被锁死,旋转后window.innerWidth不变,媒体查询无从响应 - JS 动态覆盖了初始
<meta>—— 初始设置生效后又被脚本改写,后续旋转失效
推荐写法:<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
@media (orientation: landscape) 的判定逻辑不是传感器数据
它只看 window.innerWidth > window.innerHeight 这个宽高比结果,和手机物理朝向无关。这意味着:
- 地址栏没隐藏时,
innerHeight变大,orientation: landscape可能根本不匹配(尤其 iOS Safari) - 用户把页面 zoom 很大,竖着拿手机但
innerWidth > innerHeight,照样触发横屏样式 - 折叠屏半展开、分屏模式下,
orientation会误判,而@media (max-width: 768px)之类尺寸断点更不可靠
所以别指望它“精准反映设备方向”,它只是个视口宽高比快照。
只用 @media (orientation: ...) 会延迟或漏掉首次状态
这个媒体查询在浏览器完成重排(reflow)后才重新计算,通常有几十毫秒延迟;iOS 15+ 快速旋转可能跳过触发;Android Chrome v79+ 有时只读初始方向,后续不更新。
必须配合 JS 主动检查:
- 加载时立即执行
window.matchMedia("(orientation: landscape)").matches获取初始状态 - 监听变更用
mql.addEventListener("change", ...),不是orientationchange(该事件已废弃) - IE11 要兜底用
mql.addListener(),但实际影响极小(IE11 无自动旋转逻辑)
不手动检查首次匹配,直出横屏页面就会跳过初始样式。
横屏时 100vh、100vw 容易翻车
iOS Safari 横屏下 100vh 约等于 390px(iPhone 14),但用户看到的是宽屏视图,顶部内容常被截;100vw 会包含已隐藏的地址栏高度,导致内容溢出。
实操建议:
- 优先用
100dvh/100dvw(dynamic viewport 单位),自动排除 UI 栏 - 注意 Android Chrome 100 以下不支持
dvh,需降级为height: 100%+display: flex布局 - 避免直接用
100vw设容器宽度,改用width: 100%+overflow-x: hidden
真正容易被忽略的是:横竖屏切换不是“换一套样式”就完事,而是整个视口基准(vh、vw、rem 计算根字体)都变了,必须同步调字体、行高、内边距——否则文字行宽暴增、按钮沉底不可点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











