应优先使用 screen.orientation api 而非 @media (orientation: ...),因其能获取设备真实物理朝向;需手动初始化并监听 change 事件,配合 body 类控制样式,避免 transform 旋转导致布局错乱。

@media (orientation: portrait) 和 @media (orientation: landscape) 在绝大多数实际场景中不可靠,不能作为方向切换的主力方案。
@media (orientation: ...) 为什么经常不生效
- 它只比对视口宽高比(
width > height就算landscape),不读取设备真实的物理朝向 - 桌面浏览器缩放窗口、分屏模式(如 macOS 的 Split View、Windows Snap)、折叠屏半开状态都会让判断失准
- iOS Safari 在 PWA 或 iframe 嵌入时可能完全不触发 change,Android WebView 也有类似问题
- 页面加载后方向变了,样式不会自动重算——
resize事件也不保证触发
常见现象:
- 竖屏手机横握,但
matchMedia('(orientation: landscape)').matches仍为false - iPad 横放,
clientWidth和clientHeight数值没变,媒体查询卡在旧值
用 screen.orientation + JavaScript 主动管理更稳
优先检测原生 API 是否可用,再绑定监听:
-
if ('orientation' in screen)是可靠入口 -
screen.orientation.type返回'portrait-primary'、'landscape-secondary'等真实值 - 必须手动调用一次
updateLayout()初始化,否则首屏样式错乱
示例逻辑:
if ('orientation' in screen) {
const updateLayout = () => {
document.body.className = screen.orientation.type.startsWith('portrait')
? 'orientation-portrait'
: 'orientation-landscape';
};
screen.orientation.addEventListener('change', updateLayout);
updateLayout(); // 关键:补初始化
} else {
// 降级 fallback:用 matchMedia + resize 粗略判断
const mq = window.matchMedia('(min-aspect-ratio: 1/1)');
const updateByMq = () => {
document.body.classList.toggle('orientation-landscape', mq.matches);
};
mq.addEventListener('change', updateByMq);
updateByMq();
}
注意:不要依赖 window.orientation(已废弃,Safari 早就不支持)。
CSS 类切换比媒体查询更可控
把方向状态转为 class 写在 上,后续所有样式都基于它:
- 避免重复写
@media块,维护集中 - 可叠加其他状态,比如
.orientation-landscape.theme-dark - 能配合 transition 做平滑过渡(媒体查询本身不支持动画)
对应写法示例:
.container {
width: 100%;
}
.orientation-portrait .container {
max-width: 480px;
}
.orientation-landscape .container {
max-width: 1200px;
}
别用 transform: rotate(90deg) 强行“转”元素——它不改文档流,点击热区、滚动锚点、fixed 定位全会偏移。
真正容易被忽略的点是:方向变化不是一次性事件,而是一个需要持续同步的状态。screen.orientation 提供的是当前真实朝向,@media (orientation: ...) 给的只是一个宽高比快照。
上线前务必在真机上测试热切换(旋转设备),而不是只看冷启动效果。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











