10 KiB
全项目手机视口自适应设计
背景与根因
2026-07-21 在 MuMu Android 720×1280 / 320dpi 中复核 A01 时,默认登录态无法在首屏完整显示。设备应用可用区约为 360×616dp,而 A01 仍以固定 1665rpx 画布组织纵向布局;该画布在 412×915 中接近 915px,在 360dp 宽设备中仍约为 799dp,因此必然产生滚动。
问题不是 A01 单页偏差,而是项目级合同缺失:
- 52 个活动页面虽都有
100vh或100dvh,但只有 4 页直接声明顶部安全区、9 页声明底部安全区; - 22 页只有宽度断点,项目没有统一的高度连续适配规则;
- A01、A04、A05、G01、G03、G05 仍存在大块固定
rpx高度; - 现有容量合同检查固定高度、裁切和内容是否可达,但允许自然滚动,未检查固定流程页的核心操作是否在默认手机首屏完整可见;
- 旧 A01 设计记录明确允许矮屏滚动,与用户本轮确认的产品要求冲突。
用户确认的新合同是:整个项目必须适配手机可用视口;固定流程页在默认字体下首屏展示全部核心操作,长列表、详情和文章等长内容页自然滚动;所有页面都不得裁切、遮挡或依赖固定设计稿高度。
目标与边界
- 覆盖
pages.json的全部 52 个活动路由,封存 A06 同步接受静态合同约束但不恢复路由。 - 支持当前产品使用的竖屏手机形态;基础验证宽度为 320–480 CSS px,高度从 568 CSS px 起。
- 默认系统字号下,固定流程页无需纵向滚动即可看到全部核心内容和主操作。
- 长内容页允许自然滚动,必须保证末项可达、滚动所有权清晰、固定导航不遮挡内容。
- 全部页面统一处理状态栏、刘海、底部手势区、固定 Header/Tabbar、软键盘和系统字体放大。
- 不改变页面业务语义、路由、字段、状态和视觉主题;不重绘或删除当前资产。
- 横屏不纳入本轮视觉排版目标;本轮不得通过未声明的横屏规则影响现有竖屏布局。
选择方案
采用“统一视口合同 + 页面滚动分类 + 路由保留业务布局”。
不把 52 页全部重包进一个通用页面组件,避免再次形成业务与布局耦合;不允许每页自行维护机型断点。共享层只拥有视口、安全区、触控下限和连续间距原语,每个路由继续拥有自己的内容结构。
单一所有者
运行时视口原语
styles/global.scss 是以下规则的唯一运行时所有者:
- 动态可用视口高度及
100vh兼容回退; - 顶部、底部安全区变量;
- 固定 Header 和 Tabbar 的占位变量;
- 约 44dp 的最小触控尺寸;
- 小屏到高屏连续变化的垂直间距、装饰尺寸和内容留白变量;
- 三类页面壳的基础行为。
页面可以消费这些变量,不能重新定义同义常量或按具体手机型号复制一套视口规则。
路由分类
新增一个精确路由清单作为页面分类唯一所有者。pages.json 中每个活动路由必须且只能属于一类;缺失路由、重复路由和已删除路由均使合同失败。
初始分类:
viewport-fit:A01、A04、A05、T08、F10。默认态内容有确定上限,默认字号下必须完整进入首屏。split-scroll:G01、T01、T07。页面壳固定,只有指定内容区域滚动;T01 继续保留明确的横向世系画布滚动。document-scroll:其余 44 个活动路由。内容随数据自然增长,由页面文档流承担唯一纵向滚动。
封存 A06 按 viewport-fit 静态检查,但不计入 52 页活动路由统计。
分类只决定视口和滚动合同,不提供标题、字段、状态或动作,不能成为新的业务目录配置。
三类页面行为
viewport-fit
- 页面最小高度等于实际可用动态视口,默认态不得依赖固定设计稿高度。
- 默认字体、无键盘状态下,
scrollHeight不超过可用clientHeight的像素舍入容差。 - 背景、印章、标题和留白优先使用
clamp()随可用高度连续缩放。 - 输入框、按钮、切换项、注册链接和协议勾选保持约 44dp 触控下限。
- 不允许整页
transform: scale(...),不允许隐藏核心入口,不允许把核心操作移出首屏。 - 错误文案、软键盘或系统字体放大使内容超出时,页面回退为自然滚动,不裁字、不重叠。
document-scroll
- 页面根容器至少填满动态可用视口,正文由正常文档流自然撑高。
- 页面只保留一个纵向滚动所有者;列表、详情、文章和长表单不得使用固定设计稿高度限制内容容量。
- 主操作不要求始终固定在首屏,但必须按流程顺序可达,且末项和底部按钮位于安全区及固定 Tabbar 之上。
- 空、加载、失败和短内容状态至少填满可用内容区,不能因内容少而露出错误背景或产生无意义双滚动。
split-scroll
- Header、摘要、筛选或代际栏等固定区域明确占位,指定内容区获得剩余可用高度。
- 页面文档本身不得与内部内容区同时纵向滚动。
- G01 列表、T07 目录和 T01 世系画布保持各自唯一滚动所有权;固定区域不得遮住首项或末项。
- T01 横向画布滚动与纵向视口分工继续由页面专属合同维护。
安全区与固定导航
PageHeader继续统一拥有顶部安全区和页面顶部占位。AppTabbar继续统一拥有底部安全区和页面底部占位。- 没有 Header 或 Tabbar 的页面从全局页面壳消费安全区变量,不得硬编码状态栏或手势区高度。
- 同一安全区只能由一个层级计入,禁止页面与共享导航重复叠加。
- 页面背景可以延伸到系统区域,交互内容和关键文字不能进入不可安全触控区域。
连续适配规则
- 使用
clamp(最小值, 视口相关计算值, 设计基准值)连续调整纵向尺寸,不按品牌、型号或单一分辨率写专用规则。 rpx继续用于与屏宽相关的横向比例和资产尺寸,但不得单独承担整页纵向高度合同。- 纵向压缩顺序为:装饰留白 → 装饰尺寸 → 非关键间距 → 非关键说明字号;核心文字、输入和操作触控尺寸最后压缩且不得低于下限。
- 固定像素仅用于最小触控面积、1px 线条或经审计的资产槽位,不用于限制可变正文容量。
- 旧
1665rpx等设计画布高度、重复的100vh页面壳和失效风险白名单在迁移后删除,不保留兼容分支。
字体、键盘与异常状态
- 默认字号执行页面分类的首屏或滚动合同。
- 约 1.3 倍系统字号下允许
viewport-fit页面回退为自然滚动,但所有文字必须完整、操作必须可达。 - 输入框聚焦时,软键盘不得遮挡当前字段、就近错误文案或当前主操作;页面应能滚动到焦点并在键盘收起后恢复合理位置。
- Toast、Dialog、底部弹层和全屏预览拥有独立覆盖层,不计入页面默认内容高度;它们各自处理安全区、长文案和内部滚动。
- 加载、空、失败、权限和成功状态必须按所属页面类别验证,不能只验证正常态。
合同迁移
静态合同
新增项目级手机视口合同并先在当前代码上失败,至少检查:
- 52 条活动路由与分类清单一一对应;
- 页面使用全局视口原语,不重新声明旧页面壳常量;
- 禁止活动页面以固定大块
rpx/px高度承担整页或正文布局; - 禁止整页缩放、重复安全区、双纵向滚动和无所有者的固定导航避让;
- 允许图标、缩略图、印章、按钮槽位和 T01 节点等经过精确说明的固定视觉边界;
- 白名单必须精确到文件、选择器、风险类型和原因,并拒绝失效项。
现有数据容量合同继续负责数据数量和正文增长;新合同负责手机视口、首屏、滚动所有权和安全区。两者职责不得混写。
H5 运行合同
全部 52 个活动路由至少验证:
320×568、360×616、360×640、360×800、412×915、480×1040;- 无横向溢出、无关键控件越界、无双纵向滚动;
- 安全区和固定导航不遮挡首项、末项及主操作;
viewport-fit默认态无纵向滚动;document-scroll末项可达且滚动位置稳定;split-scroll只有声明的内容区滚动;- 默认字号和约 1.3 倍字号均不裁字、不重叠。
流程页还需覆盖表单错误、提交中、失败、成功和返回保护等适用状态。
Android 验证
- 先以当前 MuMu
720×1280 / 320dpi作为 Android 基线,逐模块复核代表页和全部viewport-fit页面。 - A01 必须重新截取密码、验证码、错误、协议和键盘状态;默认密码与验证码状态无需滑动即可看到完整协议区。
- 每个模块至少检查一个短内容状态和一个长内容状态;固定 Header/Tabbar、系统返回、软键盘和底部手势区必须真实操作。
- H5 自动结果不能替代 Android 证据或用户视觉确认。
执行顺序
- 建立失败的路由分类、静态视口和全路由运行合同。
- 建立全局视口、安全区、触控和三类页面壳原语。
- 先修 A01 并在 MuMu 证明新合同可解决已复现问题。
- 迁移 A04、A05、封存 A06,再迁移 G01、T01、T07 三个特殊滚动页。
- 按 G → T → F → R → N → M 迁移剩余
document-scroll页面。 - 运行全路由六档 H5、字体压力、状态合同和 MuMu 模块复核。
- 用户逐页确认发生可见变化的页面;自动验证不得直接新增或维持
[x]。
完成条件
- 52 个活动路由全部纳入且通过项目级手机视口合同,无失效白名单。
- A01 在当前 MuMu 默认密码和验证码状态首屏完整,无需滑动。
- 六档 H5 的全部路由通过对应类别合同。
- 默认字号、1.3 倍字号、软键盘、安全区、固定导航和返回行为均有相应证据。
- 旧固定页面高度和旧自适应说明从运行时、验证器、设计记录、验收规划和交接记录中同步移除。
- Android 结论只覆盖实际验证的设备和状态,不把模拟器结果扩写为所有真机最终通过。