底部面板设计系统
目的
底部面板设计系统提供了一个标准化的、移动优先的设计框架,用于在 Web 界面和渐进式 Web 应用(PWA)中构建滑动式底部面板、操作面板和模态底部抽屉。现代移动设备的大宽高比使得顶部覆盖层和居中的模态弹窗难以单手操作。底部面板将交互任务、上下文菜单、筛选控件和详细子视图锚定在屏幕底部,处于用户拇指的自然触碰范围内。
设计一个有效的底部面板系统需要建立卡扣高度(预览/折叠、部分/半高、全高)、触摸拖拽手柄、背景变暗(遮罩)、主体滚动锁定机制、视口安全区嵌入(env(safe-area-inset-bottom)),以及无缝的响应式桌面转换(在宽视口上将底部面板转换为居中模态框或弹出框)。
使用场景
- 移动端产品选项选择器: 在电子商务产品详情页上呈现尺寸、颜色、数量和订阅周期选择器,而无需离开页面。
- 移动端筛选与排序控件: 为电子商务目录页面或 SaaS 搜索视图提供多维度筛选选项,并带有持久的底部“应用筛选”操作栏。
- 上下文操作面板: 在社交动态、媒体卡片或数据表上触发一键快速操作(分享、收藏、加入列表、举报)。
- 位置与地图详情卡片: 显示可展开的兴趣点详情或配送跟踪时间线,它们在地图视图上滑动(预览卡扣至全高展开)。
- 移动端多步子工作流: 完成快速的内联任务,例如结账支付方式选择、地址选取或快速反馈提交。
何时不使用
- 全局导航路由: 对于跨主要部分的应用程序主导航,请使用
bottom-navigation-system或site-navigation-system。 - 破坏性确认警告: 对于关键、不可逆的操作(例如“删除账户”),请使用居中的
overlay-and-dialog-system模态对话框(role="alertdialog"),要求明确确认。 - 页面内可折叠内容: 对于在页面流中切换可展开内容,请使用
accordion-ui-system或tab-ui-system。 - 宽屏桌面布局(>1024px): 不要在桌面屏幕上显示全宽底部面板。请将 UI 适配为居中模态对话框(
overlay-and-dialog-system)、侧边抽屉(dashboard-layout-system)或锚定弹出框(tooltip-and-hint-system)。
输入
- 任务类型与深度: 内容的性质(快速一键操作列表 vs. 多字段表单 vs. 可滚动详情列表)。
- 卡扣配置: 卡扣高度的选择(单卡扣:100% 全高;双卡扣:50% 半高和 100% 全高;三卡扣:20% 预览,50% 半高,90% 全高)。
- 触发上下文: 触发面板的元素或用户操作(按钮点击、长按、滑动手势或深层链接)。
- 设计令牌: 表面背景颜色、边框半径、拖拽手柄尺寸、阴影高度、遮罩不透明度以及字体排版比例。
- 桌面适配策略: 为视口 ≥1024px 选择的布局过渡方式(转换为居中模态框、转换为锚定弹出框、或转换为滑动式侧边抽屉)。
输出
- 底部面板解剖规范: 定义了拖拽手柄栏、标题(标题 + 关闭按钮)、可滚动主体、固定页脚(CTA 栏)以及安全区嵌入内边距的布局蓝图。
- 卡扣高度与手势令牌矩阵: CSS 变量和卡扣阈值定义(
--sheet-detent-peek、--sheet-detent-half、--sheet-detent-full),附带拖拽速度关闭规则。 - 遮罩与阴影规范: 遮罩不透明度令牌、遮罩模糊滤镜设置、z-index 层级以及主体滚动锁定规则(在 body 上设置
overflow: hidden)。 - 键盘与屏幕阅读器 ARIA 映射:
role="dialog"、aria-modal="true"、aria-labelledby、焦点锁定规范以及Escape键处理程序定义。 - 响应式桌面适配蓝图: 媒体查询断点,将移动端底部面板转换为平板和桌面端的居中模态对话框或弹出框。
工作流程
1. 分类面板类型和卡扣结构
根据内容量和交互频率选择合适的卡扣模式:
- 非模态操作面板(预览/自适应内容): 自动调整大小以适应短内容(2–5 个菜单操作)。高度通常在 180px 到 320px 之间。选择操作或点按遮罩后关闭。
- 半高 / 双卡扣面板(50% 和 90% 视口): 用于中等密度任务,如产品变体选择或排序。以 50% 高度(
50vh)打开;向上拖拽卡扣至 90% 高度(90vh)。 - 全高 / 可扩展面板(90%–100% 视口): 用于复杂的移动工作流,如多维度筛选或结账步骤。提供固定的标题和页脚,带有内部可滚动主体。
2. 定义视觉结构和空间层级
使用五个不同的结构层构建面板:
- 遮罩(Scrim): 覆盖整个视口的固定叠加层(
background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); z-index: 1000;)。 - 面板容器: 锚定在屏幕底部边缘的固定面板(
position: fixed; bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; background: var(--surface-bg); z-index: 1001;)。 - 拖拽手柄栏(Affordance): 顶部居中的可视小药丸(
width: 36px; height: 5px; border-radius: 999px; background: var(--border-neutral); margin: 8px auto; cursor: grab;)。 - 标题层: 包含面板标题(
h2)、可选副标题和明确的关闭按钮(<button aria-label="关闭面板">✕</button>)。 - 可滚动主体层: 内部内容容器,配置为
overflow-y: auto; -webkit-overflow-scrolling: touch;。 - 固定页脚 CTA 层: 底部锚定的操作栏,带有主要/次要按钮和安全区嵌入内边距(
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)))。
3. 建立手势、卡扣和关闭机制
为物理手势反馈设置平滑的触摸交互:
- 拖拽手柄交互: 向下拖拽手柄或标题区域,使用
transform: translateY()平滑移动面板。 - 卡扣阈值:
- 如果向下拖拽超过当前高度的 30% 或以大于 0.5px/ms 的速度向下滑动,则触发完全关闭。
- 如果在双卡扣模式下拖拽距离在 30% 到 70% 之间,则卡扣到最近的卡扣高度(50% 或 90%)。
- 滚动锁定冲突: 在可滚动主体层内拖拽时,仅在主体滚动位置为
scrollTop === 0且用户向下滑动时才启动面板拖拽关闭。 - 主体滚动锁定: 当模态底部面板打开时,对
document.body应用overflow: hidden以防止背景页面滚动泄漏。
4. 实现视口安全区和表面对比度
确保与移动硬件显示切口的视觉完整集成以及亮色/暗色模式:
- 安全区嵌入处理: 始终对面板容器或粘性页脚应用
padding-bottom: env(safe-area-inset-bottom, 16px),以便内容/按钮不会被 iOS Home 指示器遮挡。 - 最大高度限制: 将全高面板限制为
max-height: calc(100vh - 48px)或max-height: calc(100dvh - 48px),以在顶部留出 48px 的可见变暗父页面上下文切片。 - 表面阴影: 使用深层阴影令牌(
box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.15))来创建与背景页面内容的分离。
5. 配置无障碍和键盘导航
确保完全符合 WCAG 2.1 / 2.2 AA 标准:
- ARIA 角色: 容器必须使用
role="dialog"或role="region"(用于非模态预览面板)、aria-modal="true"和aria-labelledby="sheet-title-id"。 - 焦点管理:
- 打开时,编程将焦点移动到面板内的第一个可聚焦元素或关闭按钮。
- 实现一个焦点陷阱,防止
Tab或Shift+Tab使焦点离开面板进入惰性背景。 - 关闭时,将焦点恢复到打开面板的触发元素。
- 键盘控制: 按下
Escape必须立即关闭面板。 - 屏幕阅读器公告: 面板内的动态内容更改必须使用
aria-live="polite"区域。
6. 设计响应式桌面适配
当底部面板在桌面显示器(≥1024px)上全宽拉伸时,会显得不够精致。实现明确的响应式转换规则:
- 桌面模态框模式(默认): 在视口 ≥1024px 时,将底部面板转换为居中的模态对话框(
width: 100%; max-width: 540px; border-radius: 16px; margin: auto; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);)。 - 桌面弹出框模式(上下文菜单): 对于快速操作面板,将面板转换为锚定在触发按钮旁边的弹出框。
- 桌面侧边抽屉模式(复杂表单/筛选器): 对于深入的多维度筛选或多步流程,转换为右对齐的滑动式侧边抽屉(
width: 400px; height: 100vh; top: 0; right: 0; border-radius: 16px 0 0 16px;)。
决策规则
卡扣选择矩阵
| 面板类型 | 卡扣配置 | 内容量 | 理想用例 |
|---|---|---|---|
| 操作面板 | 自适应内容(单卡扣) | 2–6 个操作链接/项目 | 快速分享、上下文菜单、简单选项切换 |
| 选择面板 | 双卡扣(初始 50vh,展开 90vh) | 5–15 个可滚动项目 | 产品尺寸/颜色选择器、地址选择器、支付方式 |
| 交互式抽屉 | 三卡扣(120px 预览,50vh,90vh) | 复杂空间/地图数据 | 配送跟踪地图卡片、实时公交站点、拼车详情 |
| 全流程面板 | 单卡扣(90vh - 100vh 固定) | 多节表单/筛选器 | 目录多维度筛选、移动结账步骤、调查工作流 |
桌面转换选择
- 使用居中模态框: 当面板包含结构化表单、变体选择器或结账选项时。
- 使用锚定弹出框: 当面板包含简短的上下文操作(分享、编辑、删除)时。
- 使用侧边抽屉: 当面板包含仪表盘和数据表上的筛选控件或编辑面板时。
约束条件
- 无障碍(WCAG 2.1 / 2.2 AA):
- 当
aria-modal="true"激活时,必须提供明确的焦点陷阱。 - 所有内部项目和关闭按钮的触控目标尺寸必须至少为 44x44px(WCAG 2.5.8 / 2.5.5)。
- 模态底部面板后面的背景内容必须标记为
inert或对辅助技术隐藏。
- 当
- 触摸与手势尺寸:
- 拖拽手柄的点击目标必须通过不可见内边距放大(
min-height: 24px,min-width: 60px),即使可视手柄为 36x5px。
- 拖拽手柄的点击目标必须通过不可见内边距放大(
- 视口动态单位:
- 在支持的地方使用
dvh(动态视口高度)(height: 90dvh),并回退到vh,以适应移动端动态地址栏的展开和折叠。
- 在支持的地方使用
常见失败模式
- 缺少安全区内边距: 省略了
env(safe-area-inset-bottom),导致主要页脚操作按钮与 iOS 手势栏重叠。 - 桌面端全宽拉伸: 允许移动端底部面板在桌面显示器上扩展到 1920px 宽度。
- 滚动劫持锁定: 未能将内容滚动与面板拖拽关闭手势分离,导致用户尝试向下滚动文本时面板折叠。
- 缺少键盘关闭处理程序: 省略了
Escape键事件监听器,将桌面键盘用户困在模态面板覆盖层内。 - 焦点泄漏到背景: 当模态底部面板打开时,背景页面元素仍可通过
Tab键访问。
验证标准
- 面板布局包含明确的视觉拖拽手柄、带有标题的标题、可滚动主体和粘性页脚。
- 在粘性页脚和面板容器上实现了安全区嵌入(
padding-bottom: env(safe-area-inset-bottom))。 - 拖拽手柄的点击区域满足触摸无障碍的最小 44px 高度。
- 面板使用
role="dialog"、aria-modal="true"、aria-labelledby,并在激活时锁定焦点。 - 按下
Escape或点按遮罩会关闭模态面板,并将焦点恢复到触发按钮。 - 当模态面板打开时,背景主体滚动被锁定(
overflow: hidden)。 - 视口 ≥1024px 时,将底部面板干净地转换为居中模态对话框、弹出框或侧边抽屉。