在 Web 开发中,列表元素的使用频率极高,但许多开发者仅仅将其视为便捷的换行工具。实际上, 的核心价值在于为屏幕阅读器提供“逻辑相关项目组”的语义结构——它要求正确嵌套 以包裹完整的表单项,避免语义中断,同时结合 / 进行分组,并利用 aria-labelledby 建立清晰的层级关系。

将 或 当作换行工具,显然曲解了它们的核心功能。许多开发者倾向于使用 包裹表单字段,利用其默认换行和清晰的结构,但关键在于:屏幕阅读器会将 识别为“一组逻辑相关的项目”,并播报“列表,共 3 项”,随后逐项读出内容。这比一串孤立的 或语义杂乱的 要友好得多。不过需要警惕的是, 本身并不等同于可访问——它必须配合正确的嵌套和语义元素才能生效。
必须直接包裹完整的表单项(即与等),不能仅包裹或仅包裹- 避免在
内部嵌套或用于样式控制,否则可能破坏列表的语义流程 - 当表单需要分组时(例如“联系信息”“收货地址”),应优先使用
加,然后在其内部嵌套,而非通过 CSS 隐藏
嵌套列表中 aria-labelledby 的实际应用方法
当一个 作为子级列表(例如“支付方式”下的多个信用卡选项)时,仅靠缩进或视觉样式无法让屏幕阅读器感知层级关系。此时不能单纯依赖 CSS,而需要显式建立引用关系。常见的错误做法是为 添加 aria-label,但这会覆盖原有的列表项播报;更稳妥的方案是使用 aria-labelledby 指向一个已有的标题元素。
- 确保被引用的标题(如
)真实存在且可见 会让屏幕阅读器先读“支付方式”,再读“列表,共 2 项”,最后逐项读出内容- 不要用
aria-label替代或,因为前者无法被用户搜索、跳转或翻译
无序列表 vs 有序列表:何时必须使用
的语义并非“带数字”,而是“顺序重要”。例如步骤引导、评分标准、法律条款条目——这些场景下,改变项序会改变含义。但需要注意的是, 的默认数字样式(1. 2. 3.)对屏幕阅读器影响极小,真正起作用的是 DOM 顺序和 aria-posinset/aria-setsize(不过极少需要手动添加)。
- 纯视觉排序(如“热门服务排行”但点击后顺序可变)仍然使用
,不要为了数字强行使用 - 表单控件本身不构成顺序依赖(姓名/邮箱/电话谁先谁后不影响提交),一律使用
- 只有当你明确写出“第一步”“第二步”或逻辑上必须按序执行时,才使用
列表项内含交互控件时的焦点管理
如果 里放置了开关、复选框或自定义按钮,键盘用户在使用 Tab 导航时容易卡住——因为 默认不可聚焦,而内部控件又没有处理好 tabindex 和角色属性。最简方案是保持原生语义:
- 复选框/单选框直接放在
中,无需额外包装器,它们自带可聚焦性 - 避免给
添加tabindex="0",否则会多出一个无效的焦点停靠点 - 若必须使用自定义组件(如带图标的切换按钮),应设置
role="checkbox"或role="switch",并同步管理aria-checked和键盘事件(Space/Enter)
复杂交互列表中最容易被忽视的一点是:当某个项目被禁用(disabled)时,整个 元素应呈现视觉灰化并跳过焦点,而不是仅禁用内部控件却留下一个可聚焦的空壳。
