应使用 horizontal-viewport-segments 和 vertical-viewport-segments 判断真实双屏状态,chrome/edge 119+ 唯一稳定支持;horizontal-viewport-segments: 2 表示竖折设备完全展开,vertical-viewport-segments: 2 表示横折设备展开被垂直分割;二者值必须为整数 2,不支持嵌套媒体查询,safari/firefox 需降级处理。

用 horizontal-viewport-segments 和 vertical-viewport-segments 判断真实双屏状态
别再用 min-width: 720px 或 orientation: landscape 判断折叠屏展开态——这些在 Z Fold 半开、横折、分屏场景下全会误判。Chrome/Edge 119+ 唯一稳定可用的是 horizontal-viewport-segments 和 vertical-viewport-segments,它们直接反映物理铰链分割后的 viewport 数量。
-
horizontal-viewport-segments: 2表示竖折设备(如 Galaxy Z Fold)完全展开,左右两个独立 viewport;此时document.body.clientWidth返回的是单侧宽度(约 375–420px),不是总宽 -
vertical-viewport-segments: 2表示横折设备(如华为 Mate X3、Z Flip)展开后被垂直铰链切为上下两块,不能和horizontal混用 - 值必须是整数
2,写成>1、=2或带单位都会失效 - 不支持嵌套:不要写
@media (min-width: 720px) and (horizontal-viewport-segments: 2),部分浏览器直接丢弃整条规则 - Safari 和 Firefox 完全不支持,必须配降级样式(例如默认单栏,只在匹配时加
.is-dual-column类)
为什么 screen-spanning 不能用
screen-spanning 这个媒体特征根本不存在。它没进 CSS 标准,Chromium 早在 119 版本就废弃了,Safari/Firefox 从未实现。你写 @media (screen-spanning: single-fold-vertical),浏览器会静默忽略,DevTools 里也看不到匹配状态——不是语法错,是它压根没被解析。
- 常见错误:在真机上调试半天没反应,以为是 UA 或 JS 加载顺序问题
- 混淆点:
spanning实际用于检测“某个元素是否跨铰链渲染”,不是判断设备是否折叠;它和viewport-segments是两类东西 - 真正能响应跨铰链行为的是
@media (spanning: single-fold-horizontal),但仅限 Chrome/Edge 119+,且会导致position: sticky失效、transform 动画截断,慎用
容器查询(@container)适合组件级自适应,不适合全局折叠态切换
折叠动作改变的是整个视口(viewport),而容器查询只响应单个容器尺寸变化。它解决不了“从单列变双栏”这种整体布局切换,但对卡片、表单项等局部组件非常有效。
- 必须显式设置
container-type: inline-size和container-name,否则@container规则永不触发 - 父容器要有明确尺寸约束(比如
width、max-width,或在 Grid/Flex 中受父级限制),否则查询条件不会重算 - 不能用
@container (min-width: 500px)—— 正确写法是@container card (min-width: 500px),且括号内只能用width或inline-size - Chrome 110+、Edge 110+、Safari 16.4+ 支持,Firefox 尚未支持,线上项目需 fallback 到
@media
JS 监听要读 visualViewport.width,不是 window.innerWidth
折叠动画过程中,window.innerWidth 会剧烈跳变甚至卡在中间值,导致 resize 事件漏发或抖动。Chrome/Edge 的 visualViewport API 才反映当前渲染视口的真实尺寸。
- 监听必须在脚本加载时立即执行,不能等
DOMContentLoaded—— 折叠状态可能在 DOM 构建前就已确定 - 务必加防抖(建议 300ms),否则铰链缓慢转动时会触发几十次回调,UI 重排爆炸
- 回调里避免直接操作大量 DOM,改用
requestAnimationFrame批量更新类名或 CSS 变量 - 别用
matchMedia+window.matchMedia('(min-width: 720px)')做主判断,它无法区分 Z Fold 外屏竖屏和内屏半开态
visualViewport.width 或 horizontal-viewport-segments 这类底层信号,而不是 UA 字符串或 SDK 提供的“Foldable”标识。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











