@media (orientation: landscape) 在重排后延迟几十毫秒生效,易漏触发,必须用 window.matchmedia 监听 change 事件并手动初始化;viewport 缺 width=device-width 会导致其完全失效。

media query 触发时机不准,得手动补监听
横竖屏切换后样式没立刻变,不是 CSS 写错了,而是 @media (orientation: landscape) 在重排完成前不生效。iOS 和安卓 WebView 都有几十毫秒延迟,尤其在快速旋转时容易漏掉状态。
必须搭配 window.matchMedia 主动监听:
const mql = window.matchMedia('(orientation: landscape)');
mql.addEventListener('change', e => {
document.body.classList.toggle('is-landscape', e.matches);
});
// 首次加载也要检查
if (mql.matches) document.body.classList.add('is-landscape');
- 别用已废弃的
orientationchange事件——它只读陀螺仪角度,和实际渲染方向脱节 -
mql.matches返回的是当前真实匹配状态,比window.orientation可靠得多 - 加 class 而非直接改内联样式,方便后续用 CSS 控制动画
transform 切换比 display/visibility 更稳
用 display: none 或 visibility: hidden 切横竖屏布局,动画会卡顿甚至跳帧。因为它们触发重排(reflow),而移动端对重排极其敏感。
正确做法是用 transform: translateZ(0) 强制合成层,再配合 opacity 或位移做过渡:
.layout-portrait { transform: translateX(0); opacity: 1; }
.layout-landscape { transform: translateX(100vw); opacity: 0; }
body.is-landscape .layout-portrait { opacity: 0; transform: translateX(-100vw); }
body.is-landscape .layout-landscape { opacity: 1; transform: translateX(0); }
- 所有动画属性必须写在默认状态上,比如
.layout-portrait { transition: opacity 0.3s ease-out, transform 0.3s ease-out; } - 避免用
left或margin-left——iOS Safari 和老旧安卓 WebView 里一卡一卡 - 如果页面内容多,加
will-change: transform提前提示浏览器
viewport meta 缺失会导致 orientation 媒体查询完全失效
写了 @media (orientation: landscape) { ... } 却没反应?第一件事是检查 HTML 里的 <meta name="viewport">。
必须包含 width=device-width,否则浏览器按默认视口宽度(通常是 980px)渲染,横屏时逻辑宽度仍小于高度,orientation: landscape 根本不匹配。
- 错误写法:
<meta name="viewport" content="initial-scale=1.0">→ 缺width=device-width - 危险写法:
<meta name="viewport" content="width=375">→ 固定宽度让横屏检测彻底失效 - 推荐写法:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
flex-direction 切换时 margin 会错乱,改用 gap
竖屏用 flex-direction: column,横屏切 row,但原来写的 margin-bottom: 12px 在横排下变成“往右挤”,子项堆到一起甚至溢出容器。
根本解法是删掉所有方向性 margin,统一用 gap:
.container {
display: flex;
flex-direction: column;
gap: 16px;
}
body.is-landscape .container {
flex-direction: row;
}
-
gap是主轴间距,flex-direction变了,gap 自动对应方向 - 如果竖屏文字贴顶、横屏贴左不对齐,加
align-items: flex-start统一基准线 - 别在子项上写
margin,尤其避免margin-bottom和gap叠加
transform-origin 的坐标系跟着翻转了。比如竖屏时 transform-origin: top left 是左上角,横屏后这个“top”可能指向物理屏幕右侧——得用 center center 这类稳定锚点,或者干脆不用 origin,靠位移控制。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











