@media (orientation: landscape) 单独使用在真机上基本无效,因其依赖 viewport 正确配置(必须含 width=device-width),且仅基于宽高比快照、不响应实时视口变化;漏写或写死 viewport 会导致方向查询失效、布局错位、单位失准、flex 方向不自动翻转等问题,需结合 dvh/dvw、clamp()、显式重设及 matchMedia 动态监听。

@media (orientation: landscape) 单独写基本没用,真机上大概率不触发、延迟生效或误匹配——这不是你 CSS 写错了,而是它本身依赖 viewport 正确配置、且只看宽高比快照,不感知真实视口突变。
viewport 标签漏写 width=device-width 就直接失效
浏览器根本不会启动方向重算流程,@media (orientation: landscape) 压根不进匹配队列。iOS Safari 和 Android Chrome 都靠这个值判断是否响应旋转。
- 漏掉
width=device-width:横屏仍按竖屏宽度渲染,orientation: landscape永远为false - 写成固定值如
width=375:视口被锁死,window.innerWidth不变,媒体查询无从更新 - 被 JS 动态改写
<meta name="viewport">:初始有效,后续旋转断连
推荐写法:<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
只靠 orientation 媒体查询会触发布局错位和截断
它切换时不会自动“理解”单位基准变化,100vh、100vw、flex-direction 这些都得显式重设,否则子项堆叠、内容被切、水平溢出全来一遍。
立即学习“前端免费学习笔记(深入)”;
-
100vh在 iPhone 14 横屏下只剩约 390px,改用min-height: 100dvh(iOS 16+/Chrome 100+ 支持),降级方案是min-height: 100%+html, body { height: 100% } -
100vw在 iOS Safari 横屏时包含已隐藏地址栏高度,造成水平滚动;优先用width: 100%或100dvw(注意 Android Chrome 100 以下不支持) -
flex-direction不会自动翻转:竖屏用column,横屏必须显式写row,否则子项还是垂直堆着 -
font-size: 4vw横屏宽度翻倍,文字撑破容器;必须套clamp(14px, 2.5vw, 16px)锁死区间
微信和多数安卓 WebView 里 orientation 查询基本不可靠
微信 Android 用 X5 内核,对 screen.orientation 支持残缺;iOS 微信首次加载时 orientation 常为空或滞后。它只读系统上报的方向,不感知 window.innerHeight 从 844px 骤降到 390px 这种真实瓶颈。
- 别用废弃的
orientationchange事件,改用window.matchMedia("(orientation: landscape)")监听 - 加载时立刻执行
mql.matches获取初始状态,否则直出横屏页面会跳过样式 - 组合真实断点更稳:
@media (orientation: landscape) and (max-height: 480px)或@media (min-aspect-ratio: 13/9) - 折叠屏半开、键盘弹出时,单纯
orientation容易误判,而max-height能抓住“高度骤减”这个本质信号
rotate() 类操作会让布局彻底失控
用 transform: rotate(90deg) 强行转元素,文档流不变,但视觉尺寸和点击热区仍按原始矩形计算,fixed 元素偏移、按钮点不准、滚动条闪现全是连锁反应。
- 优先用
flex-direction或grid-template-columns重构结构,比rotate()更可控 - 真要用
rotate,必须同步交换width/height值,并设transform-origin: top left - 加
overflow: hidden防内容溢出,必要时用pointer-events: none禁用误触 - 别嵌套在
@supports里测试,有些浏览器不支持组合查询
最常被忽略的是:真机热切换(不是冷启动)才能暴露问题,比如快速旋转后 matchMedia 的 .matches 值没及时更新,或者 100dvh 在旧版 Android 上 fallback 失败——这些都得在 change 回调里用 requestAnimationFrame 补一手重排。


















