J5.10.1accessible name computation设计研究

可访问名称按固定优先级从多个来源计算得出,顺序可被开发者覆盖

别名: 可访问名称 · AccName · aria-labelledby · aria-label

概念解释

辅助技术嘴里那个控件的名字,不是「屏幕上写了什么」的别称。它是按 AccName 算法从多个来源计算出来的:可访问名称计算(accessible name computation)。优先级大致是 aria-labelledby 指向的节点文本,然后 aria-label,再然后宿主语言自己的槽(<label>、按钮的子文本、alt、输入框的 value 等),再往后才轮到 title。排在前面的来源一旦给出非空结果,后面的整段不再参与。开发者加一条更高优先级的属性,就能覆盖用户正在看的那几个字。

机制

计算是一次有序折叠,不是拼接。aria-labelledby 按 ID 顺序把若干节点的文本抽出来合成一个名字,并且允许指向看不见的节点。aria-label 是作者直接写入的字符串,它会压过按钮里面那几个字,而不是跟它们相加。原生槽位各管各的:复选框靠关联的 label,图靠 alt,链接靠子孙文本。title 是垫底,许多阅读器还把它当成描述而不是名称。

第二层是「可覆盖」这件事的工程含义。优先级表把作者属性和可见文本放进同一条赛道,作者属性在前。于是「改名字」不必改界面:加 aria-label 就能让语音、自动化、语音控制共用另一个字符串。这是有意的逃逸口,也是最容易在不知情时改写用户所见的地方。名称算完之后才轮到角色和状态被读出——计算本身不管这三者齐不齐。

怎么研究

在开发者工具的无障碍面板里读 Computed Name,不要听一遍口语就下结论。做一组最小控件:只有可见文字;加上 aria-label;再加上 aria-labelledby 指向另一段隐藏文本;只留 title。同一套在 NVDA+Firefox、JAWS+Chrome、VoiceOver+Safari 上听名称字符串,记下与面板是否一致。

自变量:名称来源组合、是否为空字符串、是否指向多个 ID。 因变量:计算名、阅读器实际语音、是否回落到下一个来源。

空的 aria-label="" 会不会阻断回落,各引擎不完全相同,这是要记的分叉,不是可以忽略的边角。

边界

SVG、MathML、表格头、input type="submit" 的默认「提交」各有宿主规则,不能拿按钮那一套优先级当全称命题。aria-labelledby 指向的节点自己又有名称来源时会递归,循环引用会被掐断,结果可能比作者以为的短。隐藏节点能否进入计算,取决于隐藏手法:display:nonearia-hidden 在不同步骤被排除。移动端阅读器有时把可见文字和计算名都念一遍,听起来像「没覆盖」,其实是冗余播报策略。

怎么落地

  • 给控件起名时先选定一个最高来源并写对,不要同时堆 aria-labellabelledby 和可见文字还指望它们相加。
  • 需要覆盖可见文字时(图标按钮、可见文字过长、多段合成),显式用 aria-labelledbyaria-label,并在检查器里确认计算名就是那一串。
  • 不要留空的 aria-label 或指向已删除节点的 labelledby 去「占位」,它可能阻断回落到可见文字。
  • 验证:打开无障碍面板看每一个交互节点的 Computed Name;再用 NVDA 只听名称(不展开描述)。面板里的字符串与语音不一致,或与作者以为的来源不一致,就是优先级被写错或被空值截断。

延伸

  • 同组J5.10.2 视觉可见的文字与实际计算出的可访问名称可能不一致 · J5.10.3 状态变化(展开、选中、禁用)需要实时同步到无障碍树而非仅改变外观 · J5.10.4 自定义组件常见的失误是提供了角色却遗漏了对应状态属性
  • 相邻J5.02 无障碍树与角色 · J5.04 语音控制
  • 站内检索accessible name computation · aria-labelledby · AccName

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/J5.10.1