自定义选择框与组合框系统 是做什么的?
目的
自定义选择框与组合框系统提供了一套系统化的方法论,用于设计和构建下拉选项、自动补全搜索选择器(组合框)以及多选标签输入。
标准的HTML <select> 元素在不同浏览器中难以保持一致的样式,并且无法支持丰富的布局组合(如单个选项中的描述、图标、徽章或子网格)。然而,自定义下拉框通常是严重的可访问性失败、键盘陷阱和可用性错误的根源。本技能建立了设计、空间和交互标准,以确保自定义选择组件在视觉上保持连贯、高度响应且完全可访问(符合WCAG 2.2 AA标准)。
用例
在以下情况下应用此系统:
- 富内容下拉框: 需要视觉指示器、副标题、辅助元数据或状态徽章的选择项(例如,带有国旗图标的国别选择器、工作区切换器或账户资料)。
- 可搜索选择器(组合框): 选项超过10个的下拉框,用户必须能够通过内联搜索输入过滤选项(例如,长列表的州/省选择、标签选择)。
- 多选标签字段: 允许多选且需将选择项渲染为可关闭的徽章/标签并放置在触发器容器内部或旁边的字段。
- 动态配置过滤器: 需要丰富布局对齐和即时上下文反馈的高密度过滤控件(例如,电子商务或数据仪表板的侧边栏)。
不适用场景
请勿在以下情况使用此系统:
- 低选项数量(2 到 5 个选项): 使用
分段控件系统或标准的分组单选按钮。这可以避免将选项隐藏在额外的点击后面,并降低认知负荷。 - 全局页面导航: 如果点击下拉项会立即将用户重定向到不同的页面或站点节点,请使用
站点导航系统或嵌套下拉菜单。选择输入是用于编辑属性的语义化表单字段,不应用于站点地图的遍历。 - 标准的无样式表单: 对于通用、低优先级或实用表单(如基本的联系字段),请默认使用原生浏览器
<select>输入。原生下拉框具有完美的、免费的移动端响应能力和原生屏幕阅读器支持。 - 全屏命令面板: 如果目标是搜索整个应用的页面和操作,而不是选择单个表单值,请使用
命令面板系统。
输入
在设计自定义选择框或组合框之前,请收集以下需求:
- 选项基数与密度: 有多少个选项(例如,5、50、500+)?最大字符长度是多少?
- 选择类型: 单选 vs. 多选?静态列表 vs. 异步过滤查询列表(组合框)?
- 数据丰富度: 选项是否需要辅助视觉元素(图标、头像、国旗、色块)或支持性文本(子标签、价格修饰符、活跃用户数)?
- 布局上下文: 它将位于高密度侧边栏、宽敞的登录页面、覆盖模态框还是持久设置仪表板?
- 品牌令牌: 间距比例(
fluid-spacing-system)、字体比例(fluid-typography-system)、焦点环(focus-indicator-design-system)和投影阴影比例(elevation-and-depth-system)。
输出
此系统生成以下设计交付物:
- 结构规范: 详尽的蓝图,显示触发器和下拉面板的间距、对齐、图标、文本截断规则以及边框/背景层。
- 状态与交互矩阵: 定义了悬停、激活/打开、选中、聚焦、禁用和验证错误状态的视觉样式。
- 响应式适配模型: 关于桌面下拉框如何适配移动端视口的结构规范(例如,转换为底部抽屉/面板或原生回退覆盖层)。
- 无障碍映射(WAI-ARIA 和键盘): 精确的角色、实时区域声明、焦点跟踪状态和键映射行为,以便移交给开发人员。
工作流程
1. 构建组件解剖结构
一个完整的自定义选择系统由两个主要空间层组成:
A. 触发器(字段)
- 容器: 高度与相邻表单输入匹配(通常为 40px 到 48px 以确保触摸目标)。使用中性轮廓(与页面背景对比度不低于 3:1)并定义内边距(通常为
12px 16px)。 - 值/占位符插槽: 位于左侧。非活动文本代表占位符(对比度不低于 4.5:1)。选中文本使用主要中性字重。
- 视觉提示(箭头图标): 位于最右侧。使用独特的向下箭头表示可折叠内容。当菜单激活时,将箭头旋转 180 度。
- 选中徽章(仅多选): 紧凑的内联标签,带有单独的关闭(x)控件,可以优雅地换行或使用计数修饰符截断(例如,"+3 more")。
B. 下拉面板(菜单)
- 覆盖容器: 位于更高的 Z 轴层级(
elevation-and-depth-systemLevel 3/4)。默认在触发器下方渲染,如果视口边缘限制了下部空间,则在触发器上方渲染。使用明显的阴影(例如,带有柔和模糊的box-shadow)使其与背景页面分离。 - 滚动容器: 设置最大高度约束(通常为
240px到320px/ 5–8 项),以防止面板溢出页面。对于较长的列表,使用可见的、防止滚动条移位的滚动轨道。 - 搜索输入(仅组合框): 固定在面板顶部的搜索输入,在菜单激活时保持焦点。
C. 选项项(选择项)
- 布局: 水平弹性布局,左侧为可视化资源,中间为主文本(如果为富选项则包含副标题),右侧为选中状态指示器(如勾选标记)。
- 安全内边距: 最小垂直内边距为
8px,水平方向与触发器的水平内边距匹配(12px到16px)。
+------------------------------------------+
| Select Country [v] | <-- 触发器(关闭)
+------------------------------------------+
+------------------------------------------+
| [Q] Search countries... | <-- 固定的搜索输入
+------------------------------------------+
| [x] Canada | <-- 选项(选中并聚焦)
| ISO: CA | +1 Country Code |
|------------------------------------------|
| [ ] Germany | <-- 选项(默认)
| ISO: DE | +49 Country Code |
+------------------------------------------+
2. 制定状态与反馈矩阵
为组件的每个生命周期状态设计明确、无歧义的样式:
- 默认状态: 触发器使用清晰的轮廓(与页面背景对比度不低于 3:1)和清晰的文本标签(对比度不低于 4.5:1)。
- 悬停状态: 触发器和选项行上使用微妙的背景色调变化(例如,低对比度灰色),以指示可交互性。光标设置为
pointer。 - 聚焦状态: 在活动元素周围使用高度可见的焦点环。对于组合框,当列表打开时,焦点应位于搜索输入上,但在高亮显示的列表选项上使用视觉焦点处理(例如,背景色调或活动轮廓)。
- 激活/展开状态: 箭头旋转,触发器轮廓颜色变化(例如,主品牌色),下拉面板以平滑的高度和透明度过渡出现(150ms 到 250ms)。
- 选中状态: 选中时选项行视觉变化。在最右侧使用高对比度的勾选图标和微妙的背景填充。不要仅依赖颜色来表示选中状态。
- 禁用状态: 视觉透明度降低至 40%–50%。光标变为
not-allowed指示符,并且该元素在标签索引中被跳过。 - 错误/无效状态: 触发器轮廓变为验证错误颜色(通常为高对比度红色,不低于 3.1 对比度),并在输入下方附带错误消息和错误图标。
3. 建立空间与放置规则
为避免布局冲突和累积布局偏移 (CLS):
- 动态定位(翻转行为): 计算视口边界。如果下拉容器靠近视口底部折叠区,则将其对齐方向翻转,使其向上滑动到触发器上方。
- 宽度对齐: 下拉面板必须与触发器的左右边缘精确对齐,或者具有与触发器匹配的定义最小宽度,以防止视觉不稳定。
- 覆盖隔离: 使用符合高程系统中 Level 3(粘性/浮动 UI)或 Level 4(覆盖和对话框)的 CSS
z-index堆栈。始终确保面板渲染在相邻表单元素、背景和布局卡片之上。
4. 设计响应式与移动端适配
切勿将多列或宽桌面下拉菜单强制塞入小屏幕移动端视口。应用以下适配布局规则:
模式 A:移动端底部抽屉(推荐用于富选项)
在屏幕尺寸低于 640px(或标准平板断点)时,将自定义下拉面板转换为滑入式底部抽屉:
- 触发器: 点击触发器打开一个全宽底部抽屉覆盖层。
- 遮罩层: 半透明深色背景(40% 到 60% 不透明度)覆盖主要内容,使背景元素不可交互。
- 头部: 抽屉包含一个固定头部,带有清晰的标题和一个大尺寸、易于触摸的关闭(x)按钮,位于右上角。
- 拇指可触及性: 选项行占据全屏宽度,并增加触摸目标高度(最小 48px,推荐 56px),以便轻松进行手指点击选择。
模式 B:原生回退(推荐用于简单列表)
在移动端视口上,完全对屏幕阅读器和视觉 DOM 隐藏自定义标记,替换为视觉隐藏、层叠的原生 <select> 元素:
- 工作原理: 将一个标准
<select>元素直接定位在自定义触发器上,并使用opacity: 0样式。 - 结果: 用户看到您的自定义品牌触发器,但点击它激活的是原生的 OS 选择滚轮(iOS 选择器或 Android 对话框)。这提供了无与伦比的原生性能和本地可访问性。
5. 定义屏幕阅读器与键盘架构
自定义选择元素必须支持完整的辅助技术。为交接指定精确的行为:
ARIA 映射与语义
- 触发器按钮: 必须具有
role="combobox"、aria-haspopup="listbox"、aria-expanded="true/false"和aria-controls="listbox-id"。 - 下拉面板: 必须具有
role="listbox",并通过触发器的 ID 标记(aria-labelledby="trigger-id")。 - 选项项: 必须具有
role="option"。当前选中的项必须具有aria-selected="true",其他项必须具有aria-selected="false"。 - 焦点管理: 对于自动补全组合框,搜索输入必须具有
aria-autocomplete="list"。在输入上使用aria-activedescendant="option-id"来跟踪用户使用箭头键上下移动时视觉高亮显示的选项。 - 实时公告: 使用
aria-live="polite"或指定的屏幕阅读器公告元素来广播选择状态更改或计数更新(例如,"找到 5 个选项。使用箭头键导航。")。
键盘交互表
您的规格说明书必须强制要求这些精确的热键映射:
| 操作 | 按键 | 预期行为 |
|---|---|---|
| 打开菜单 | Space 或 Enter 或 ArrowDown | 打开下拉面板,将焦点置于第一个选项(或搜索框)上。 |
| 关闭菜单 | Escape 或 Tab | 关闭面板,将键盘焦点返回到触发器。 |
| 导航选项 | ArrowDown / ArrowUp | 将活动高亮状态移动到下一个或上一个选项行。 |
| 选择选项 | Space 或 Enter | 选中高亮显示的选项,更新值,关闭面板。 |
| 第一/最后一项 | Home / End | 将活动高亮移动到选项列表的绝对开始或结束。 |
| 跳转搜索 | 任意字母数字键 | 如果是静态列表,焦点立即跳转到以该字母开头的第一个选项。 |
决策规则
自定义选择选项决策树
总共有多少个选项?
├── 2 到 5 个选项 ─────────> 使用分段控件或分组单选按钮
├── 6 到 10 个选项 ────────> 使用自定义选择框(单列,无搜索输入)
└── 超过 10 个选项 ────> 使用组合框(带有集成搜索输入的自定义选择框)
选择正确的选择模式
| 需求 | 使用标准选择框 | 使用可搜索组合框 | 使用多选标签 |
|---|---|---|---|
| 选择限制 | 仅单个值 | 仅单个值 | 同时多个值 |
| 选项规模 | 6 到 15 项 | 15 到 100+ 项 | 5 到 50 项 |
| 摩擦类型 | 低探索 | 需要快速目标检索 | 累积组合 |
| 选项布局 | 简单文本行 | 简单或富列表行 | 标签/标记换行布局 |
约束条件
- 焦点保留: 通过
Escape或点击外部关闭下拉框时,焦点绝不能丢失或重置到站点地图的顶层。它必须以编程方式返回到触发器元素。 - 焦点可见性 (WCAG 2.2 SC 2.4.11): 触发器或活动选项上的焦点指示器绝不能隐藏或被粘性页面头部、浮动底部栏或重叠的覆盖层遮挡。
- 触摸目标 (WCAG 2.2 SC 2.5.8): 每个选项行和触发器元素必须具有最小可点击尺寸
24x24px,而40px到48px的高度是默认布局要求,以避免在移动设备上发生触摸重叠。 - **颜色对比度 (WCAG ...