Web 网页应用如何适配 iPhone Duo 上的 Safari?
Apple 还没有发布 web 适配指南,WebKit 官方博客是目前唯一可信的参考:先按响应式设计做,再用 Device Posture API 与 Viewport Segments API 处理折叠状态,最后别忽略外屏侧边的控件区。
截至 2026 年 10 月 28 日,Apple 还没有发布任何面向 web 的 iPhone Duo 适配指南。目前唯一一份来自官方的技术说明,是 WebKit 博客 10 月 23 日的《WebKit Features for Safari 27.1》。
这篇文章的核心结论只有一句:没有新闻。iPhone Duo 上的 Safari 用的是同一套 WebKit、同一批 web 技术,网站与 web 应用照常工作,不需要为它单独做一个版本。
但「照常工作」不等于「什么都不用管」。下面按能落地的顺序拆开:先看视口范围,再讲 iPhone Duo折叠屏网页适配的基本盘,然后是 Safari 折叠屏适配里唯一由系统接管的行为,接着回答 web 如何判断折叠屏状态、web 如何判断设备是折叠屏这两个最容易混淆的问题,最后给出网页如何适配iPhone Duo 的清单。
一、先看视口:382 到 951
WebKit 给了一张 Safari 27.1 的视口表,覆盖各种姿态(CSS 像素):
| 姿态 | 宽度 | SVH | LVH |
|---|---|---|---|
| 外屏,竖屏 | 382 | 580 | 618 |
| 外屏,横屏 | 594 | 368 | 406 |
| 内屏,竖屏(单标签页) | 669 | 867 | 902 |
| 内屏,横屏(单标签页) | 951 | 585 | 620 |
| 内屏,横屏双窗口(每个窗口) | 385 | 571 | 609 |
三条结论:
- 宽度范围是 382–951,高度范围是 368–902。 这个区间和其他 iPhone 有重叠,所以不能靠宽度反推机型。
- 内屏的标签栏在顶部,像 iPad 或 Mac;外屏在底部,和普通 iPhone 一样。用户滚动时,标签栏会缩小。
- 内屏横屏可以并排两个窗口,每个窗口拿到的是一个窄的竖屏视口(385 宽)。
这些数字不需要写进代码。用媒体查询加 Grid / Flex 的流体布局把 382–951 整个区间覆盖住就够了。
二、iPhone Duo折叠屏网页适配:先做响应式,别做设备嗅探
WebKit 的建议很直接:不要用 UA 嗅探判断设备,改用特性检测。理由不只是「UA 不可靠」——折叠屏的姿态变化本来就不会反映在 UA 里,而且 Duo 的视口和普通 iPhone 有交集。
iPhone Duo折叠屏网页适配的第一层,其实就是最普通的响应式设计:
.grid {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}
再补两条容易忽略的:
- 高度别用
100vh。 表格里的 SVH / LVH 两列已经说明了浏览器工具栏会伸缩;优先用svh、lvh、dvh。 - 断点按内容宽度定,不按机型定。 320 / 480 / 720 这类通用断点比「Duo 内屏 669」更稳,设备换代也不用改。
三、Safari 折叠屏适配:唯一被系统接管的是 PDF
Safari 27.1 面向用户只改了一件事:当用户像看书一样半折着看网页 PDF 时,Safari 自动把 PDF 显示成左右两页;摊平或完全合上后,回到单页。
这是浏览器行为,网站不需要做任何事,也没有 CSS 能控制它。所以 Safari 折叠屏适配的重点不在 PDF,而在两件事:视口变化时布局别崩,控件位置变了别挡住内容。
除此之外,Safari 并没有为折叠屏增加「自动分栏」「自动重新排版」之类的能力。想在半折时把内容分到两侧,得自己写,也就是下面两个 API。
四、web 如何判断折叠屏状态:Device Posture API
Safari 27.1 在 iPhone Duo 上以开发者预览的形式提供了 Device Posture API 和 Viewport Segments API,默认关闭。打开路径是:设置 > App > Safari > 高级 > 功能开关,把「Device Posture API」和「Viewport Segments API」都打开。
Device Posture API 只有两个值:
folded:设备处于部分折叠,书本或笔记本姿态;continuous:屏幕是平的,包含完全展开和完全合上。
CSS 里用媒体查询:
@media (device-posture: folded) {
.layout {
display: grid;
grid-template-columns: 1fr 1fr;
}
}
JavaScript 里读 navigator.devicePosture.type,并监听 change 事件:
function reportPosture() {
console.log(`Device posture: ${navigator.devicePosture.type}`);
}
reportPosture();
navigator.devicePosture.addEventListener("change", reportPosture);
一个必须记住的边界:continuous 把「完全展开」和「完全合上」合并成了一个值。所以 web 如何判断折叠屏状态这个问题,API 只能回答「现在是不是半折」,回答不了「现在用的是内屏还是外屏」。
五、web 如何判断设备是折叠屏:没有可靠答案,也不该判断
这是最容易写错的一节。Device Posture API 只能描述当前姿态,不能说明设备身份:
- 普通 iPhone 上,
navigator.devicePosture可能根本不存在; - 折叠屏完全摊平时,
type也是continuous,和普通 iPhone 无法区分; - UA 字符串同样不行,WebKit 明确建议不要做 UA 嗅探。
所以严格来说,web 如何判断设备是折叠屏,目前没有官方答案。能做的是能力探测,不是设备判定:
const hasPosture = "devicePosture" in navigator;
const segments = window.viewport?.segments ?? [];
即便探测到 window.viewport.segments 返回两段,那也只能说明「当前屏幕被折痕分成两块」,不能反推设备型号:内屏横屏并排两个窗口时,同样是两块视口。
正确的思路是放弃「判断设备」,改成「判断可用空间」:空间够就上双栏,不够就单栏;半折且 API 可用时再按折痕对齐。这样无论将来出什么形态,布局都不用重写。
六、Viewport Segments:真正能绕开折痕的 API
Viewport Segments API 描述的是折痕两侧的「段」。Safari 27.1 在功能开关打开后支持两个媒体查询:
horizontal-viewport-segments: 2:左右并排,书本姿态;vertical-viewport-segments: 2:上下堆叠,笔记本姿态。
要让内容精确贴合每一段的边缘,API 提供六个环境变量:viewport-segment-width、viewport-segment-height、viewport-segment-top、viewport-segment-right、viewport-segment-bottom、viewport-segment-left。每个变量带两个索引:先列、后行,从左上角的 0 0 开始。并排时左边是 0 0、右边是 1 0;堆叠时上边是 0 0、下边是 0 1。
@media (horizontal-viewport-segments: 2) {
.wrapper {
display: grid;
grid-template-columns:
env(viewport-segment-width 0 0)
env(viewport-segment-width 1 0);
}
}
JavaScript 侧用 window.viewport.segments 拿到一组 DOMRect,姿态变化或窗口尺寸变化时重读:
function reportSegments() {
window.viewport.segments.forEach((segment, i) => {
console.log(`Segment ${i}: ${segment.width}px × ${segment.height}px`);
});
}
reportSegments();
navigator.devicePosture.addEventListener("change", reportSegments);
window.addEventListener("resize", reportSegments);
要提醒的是,这两个 API 现在都在功能开关后面,真实用户默认关闭。所以它们只能当增强手段,不能当唯一布局方案——没开开关时,页面必须仍然完整可读,靠的还是第二节那套响应式布局。
七、外屏侧边控件:背景色是现在唯一能做的事
外屏比普通 iPhone 更宽更短,iOS 为了把垂直空间留给内容,把控件移到了侧边。
Safari 27.1 里,网页内容目前不会延伸到这些控件后面。Safari 会读取页面背景色,用它把控件周围的空间铺满。WebKit 说他们在考虑放开这块区域,也提到 viewport-fit=cover 这个方向,但同时承认:现状是很多站点四边安全区都没处理对,所以还在找一个更稳妥的方案,目前没有结论。
在官方方案落地前,能做的只有三件小事:
- 给
body设一个和页面顶部一致的背景色,避免侧边出现割裂的色块; - 固定定位元素用
env(safe-area-inset-*)留边距,别贴着屏幕边缘; - 注意顶部粘性导航:内屏标签栏在顶部,粘性头部不要和它抢同一块位置。
八、网页如何适配iPhone Duo:六步清单
- 媒体查询覆盖 382–951px,断点按内容宽度写,不按机型写;
- 高度用
svh/lvh/dvh,不用100vh; - 用
@media (device-posture: folded)做半折时的分栏增强,不支持时保持单栏; - 需要贴着折痕排版时,用 Viewport Segments 的
env()对齐两侧; - 所有折叠相关样式都放在特性检测之后,功能开关没开时页面依然完整;
- 用 Xcode 27.1 或更高版本的 Device Hub 模拟器测各种姿态,不必等真机。
九、测试:不用真机
WebKit 明确说,测试不需要 iPhone Duo 在手:下载 Xcode 27.1 或更高版本,用 Device Hub 创建 iPhone Duo 模拟器即可。在模拟器里的 Safari 打开功能开关,就能验证姿态与分段。
需要过一遍的姿态:外屏竖屏、外屏横屏、内屏竖屏、内屏横屏、内屏横屏双窗口、半折书本、半折笔记本。重点看三处:内容有没有被折痕或控件挡住、展开合拢时状态有没有丢、双栏在 385px 宽的窗口里会不会挤爆。
十、参考
- WebKit Features for Safari 27.1(WebKit 博客,2026 年 10 月 23 日)
- Device Posture API(MDN)
- Viewport Segments API(MDN)
- Alternatives to UA sniffing(MDN)
Apple 官方 web 适配指南尚未发布,本文依据 2026 年 10 月 23 日的 WebKit 博客整理;官方文档上线后以原文为准。如果你的站点在 Duo 上遇到了上面没覆盖的问题,欢迎通过页脚的反馈表单告诉我们。