应使用horizontal-viewport-segments和vertical-viewport-segments媒体特性识别折叠屏真实分屏状态,Chrome/Edge 119+支持,需配合@supports降级,避免嵌套查询与screen-spanning等废弃特性,并用visualViewport.width防抖监听。

不能只靠 @media (min-width: 768px) 或 @media (orientation: landscape) —— 这些查的是屏幕尺寸或方向,根本识别不了折叠屏的物理分屏状态。Z Fold 半开时、Pocket 展开时,这些查询全会误判。
用 horizontal-viewport-segments 和 vertical-viewport-segments 判断真实分屏
这是目前唯一能反映铰链是否实际分割视口的 CSS 媒体特性,Chrome/Edge 119+ 稳定支持,Safari/Firefox 尚未实现。
-
horizontal-viewport-segments: 2表示竖折设备(如 Z Fold)已完全展开,浏览器渲染左右两个独立视口,document.body.clientWidth返回单侧宽度(约 375–420px),不是总宽 -
vertical-viewport-segments: 2表示横折/翻盖设备(如 Pocket)已展开,高度被物理分割,此时才该用 height 相关布局逻辑 - 值只能是整数
1或2,不能写>1、=2或min-horizontal-viewport-segments - 不能嵌套在其他查询里,例如
@media (min-width: 768px) and (horizontal-viewport-segments: 2)会直接失效
必须加 @supports 降级,否则样式全丢
不加 @supports (horizontal-viewport-segments: 2),Safari、Firefox 和旧版 Chrome 会跳过整个 @media 块,导致适配规则完全不生效。
- 正确写法:
@supports (horizontal-viewport-segments: 2) { @media (horizontal-viewport-segments: 2) { /* 样式 */ } } - 避免同时定义
horizontal-viewport-segments和vertical-viewport-segments规则覆盖同一元素——CSS 变量如--fold-state会被后声明的覆盖,建议统一在:root设一个 - 别碰
screen-spanning:它没进标准,Chromium 内部已标记“废弃”,MDN 都移除了文档,DevTools 里根本看不到匹配状态
JS 监听要防抖,且读 visualViewport.width
CSS 媒体查询只响应静态状态,但折叠过程有半开、动画帧、系统延迟上报等中间态,matchMedia 会频繁触发 false positive。
- 监听方式:
const mq = window.matchMedia('(horizontal-viewport-segments: 2)'),不是window.onresize - 必须加至少 100ms 防抖,否则 UI 会疯狂抖动
- 取值要用
visualViewport.width:它反映当前渲染视口的实际宽度;window.innerWidth在折叠过渡期常返回错误值(比如仍维持展开前尺寸) -
iframe内无法访问visualViewport,脚本必须运行在顶层上下文
安全区留白要用 env(safe-area-inset-bottom) + 层叠降级
折叠屏底部操作条是系统级浮层,仅靠给 body 加 padding-bottom 推不开它;真正要作用于可滚动容器,且必须双写 fallback。
- 确保
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">已设置,否则env()全部返回0px -
env(safe-area-inset-bottom)在非折叠/非刘海设备上返回0px,不是未定义,所以不会触发回退——必须靠层叠:先写padding-bottom: env(safe-area-inset-bottom),再写padding-bottom: 20px - 优先作用于实际滚动区域,比如
.main-content或main,而不是html或body - 固定定位按钮需额外加
bottom: env(safe-area-inset-bottom),否则会被遮挡 - 别用
calc(16px + env(safe-area-inset-bottom))包裹整个间距——结果会叠加,超出预期
真正麻烦的不是语法写对,而是不同浏览器在不同折叠阶段给出的反馈不一致:Chrome 里 horizontal-viewport-segments 刚变成 2 的那一刻,Safari 里可能还卡着不动,这种时间差必须靠 JS 防抖 + CSS fallback 共同兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











