你以为折叠屏适配只能靠orientation判断?今天四个CSS媒体查询把这件事彻底原生化了
写过移动端适配的人都踩过这个坑——页面在折叠屏上打开,内容刚好被铰链切成两半,字刚好断在折缝里。你以为这是硬件问题,其实是你的 CSS 根本没拿到折叠屏的状态信息,只能靠 orientation: landscape 猜,猜对了算运气好。
这件事今天被 Viewport Segments API 彻底原生化了。
旧方案为什么不行
以前做响应式,你用的是这套:
/* 只能判断横屏竖屏,跟折叠状态毫无关系 */
@media (orientation: landscape) {
.layout { flex-direction: row; }
}
问题是:一部折叠屏展开成平板形态,orientation 仍然是 portrait,但你实际上有了左右两个屏幕区域。这套逻辑在 Z Fold 半开状态、横折展开状态、分屏多窗口状态下全部失效。
你只能靠 JavaScript 监听 resize,然后手动算 window.innerWidth 落在哪个区间,再动态计算每个区域该多宽。这套方案脆弱到换一个机型就要重调。
四个媒体查询,把折叠状态说清楚了
Chrome 138/Edge 138 稳定支持 Viewport Segments API,给了你两个正交的维度:
/* 水平方向被分割成几块(竖折手机展开 → 左右两个屏) */
@media (horizontal-viewport-segments: 2) { }
/* 竖直方向被分割成几块(横折平板展开 → 上下两个屏) */
@media (vertical-viewport-segments: 2) { }
这两个值是独立的,可以组合:
/* 竖折手机完全展开:左右两块屏 */
@media (horizontal-viewport-segments: 2) and (vertical-viewport-segments: 1) {
.layout { display: flex; }
}
/* 横折平板完全展开:上下两块屏 */
@media (horizontal-viewport-segments: 1) and (vertical-viewport-segments: 2) {
.layout { flex-direction: column; }
}
这才是真正的「硬件感知」——它告诉你的是物理屏幕怎么被分割,而不是屏幕旋转了几度。
拿到分割尺寸:env() 变量
光知道有几块屏还不够,你还得知道每块有多宽、有多高、铰链占多少空间。六个环境变量把这件事说清楚了:
.wrapper {
display: flex;
height: 100%;
}
@media (horizontal-viewport-segments: 2) {
.list-view {
/* 左侧第一块屏的宽度 */
width: env(viewport-segment-width 0 0);
}
.fold {
/* 铰链宽度:右侧起点 - 左侧终点 */
width: calc(
env(viewport-segment-left 1 0) - env(viewport-segment-right 0 0)
);
background-color: black;
}
.detail-view {
/* 右侧第二块屏的宽度 */
width: env(viewport-segment-width 1 0);
}
}
第一个数字是 segment 索引(0 = 第一块,1 = 第二块),第二个是轴向(0 = 主轴,1 = 副轴)。你可以精确算出铰链的宽度,然后把内容对齐到真实屏幕边界,而不是对齐到虚拟的屏幕中线。
完整落地例子
以一个常见的邮件列表场景为例:
<div class="wrapper">
<aside class="list-view"></aside>
<div class="fold-gutter"></div>
<main class="detail-view"></main>
</div>
/* 普通手机:单栏 */
.wrapper { display: flex; flex-direction: column; }
/* 竖折屏展开:列表在左,详情在右,铰链有独立间距 */
@media (horizontal-viewport-segments: 2) {
.wrapper { flex-direction: row; }
.list-view {
width: env(viewport-segment-width 0 0);
}
.fold-gutter {
width: calc(
env(viewport-segment-left 1 0) - env(viewport-segment-right 0 0)
);
}
.detail-view {
width: env(viewport-segment-width 1 0);
}
}
整个方案不需要一行 JavaScript。CSS 自己读到了硬件状态,布局自动适配。
浏览器支持现状
| 特性 | Chrome/Edge | Firefox | Safari |
|---|---|---|---|
| horizontal-viewport-segments | 138+ | ❌ | ❌ |
| vertical-viewport-segments | 138+ | ❌ | ❌ |
| env(viewport-segment-*) | 138+ | ❌ | ❌ |
Chrome 和 Edge 全面支持,Firefox 和 Safari 还未跟进。生产环境建议渐进增强:
/* 默认:单栏布局,所有浏览器都正常工作 */
.layout { display: flex; flex-direction: column; }
/* 增强:只有支持的浏览器才响应折叠状态 */
@supports (horizontal-viewport-segments: 2) {
@media (horizontal-viewport-segments: 2) {
.layout { flex-direction: row; }
/* ... */
}
}
不支持的浏览器继续走单栏,不影响功能。
下一步
现在去 Chrome DevTools 打开设备模拟,选择「Samsung Galaxy Z Fold」或「Surface Duo」,切换到「Spanned」模式,看你的页面布局有没有被铰链影响。如果有,这套 API 就是你等了很久的答案。
官方 Demo 和规范在 Chrome Foldable APIs 页面可以找到,MDN 上有完整的 env() 变量对照表。
评论区
登录后可评论。