健壮:内容需能被各类辅助技术解析
别名: 健壮 · POUR robust · 辅助技术兼容
概念解释
自绘的开关鼠标点得动,旁边还写着「通知」,换到阅读器里却变成无名的「可点击」。换一套 JAWS 加 Chrome,连「可点击」也不报了。健壮(robust)问的不是人看不看得见、按不按得下,而是这份内容能不能被当下的浏览器和辅助技术解析成稳定的结构——有名称、有角色、有状态,并且这份结构在常见组合里还活着。
「我们在最新 Chrome 里测过」不是健壮。健壮处理的是交换格式:辅助技术不读像素,读可访问性树。树塌了,前三项原则对人眼成立,对机器仍然是空的。
机制
辅助技术是另一类用户代理。它消费的是无障碍树(accessibility tree),不是视觉布局。角色决定「这东西能做什么」的预期,名称决定怎么称呼它,状态决定它现在是开还是关。自定义控件如果只在画布上像复选框,树上却是普通分组,阅读器就无法提供空格切换那套约定。无效标记、把整页做成一张图、用 CSS 内容冒充真正的文本节点,都会让这棵树残缺或撒谎。
第二层是多样性,不是单一引擎。用户的组合是 NVDA 配 Firefox、JAWS 配 Chrome、VoiceOver 配 Safari、TalkBack 配系统浏览器——每一对都有自己的漏洞和虚拟缓冲实现。健壮要求内容走被广泛实现的语义(HTML 控件、经过验证的 ARIA 模式),而不是赌某一对组合的私有行为。POUR 把它放在最后,因为感知、操作、理解都可以在「视力正常、用鼠标、用一个浏览器」的测试里全部通过,而树仍然是空的。
怎么研究
打开无障碍树或等效检查器,逐个交互控件看 Name、Role、Value/State 是否齐。再用真实组合跑同一条任务:NVDA+Firefox、JAWS+Chrome、VoiceOver+Safari;移动端加 TalkBack。记录「某一套能走、另一套全哑」的点,那是健壮失败,不是「用户不会用阅读器」。
自变量:标记策略(原生控件 / 合法 ARIA / 纯画布 / 无效嵌套)、浏览器与 AT 组合。 因变量:树上是否同时有名称、角色、状态;任务在几套组合里能完成;只在一套组合里成功的步骤数。
自动化能抓到缺失角色、错误的 ARIA 引用,抓不到「这套组合的虚拟缓冲把实时区域吞了」。兼容性矩阵替代不了,但也不能用某一套的通过去宣称全部通过。
边界
尚未被任何 AT 实现的全新交互(某些 WebXR 控件、自研画布编辑器)可能暂时没有可解析的映射;这时健壮退化为提供一份 AT 能用的替代视图,而不是假装 3D 场景已经在树上。内嵌的第三方小部件若完全失控,整页健壮会被一块 iframe 打断——责任在嵌入决策,不在「我们自己的按钮都是原生的」。定期的浏览器/AT 升级会把昨天还健壮的内容弄坏,健壮是持续属性,不是一次构建的勋章。纯静态、无脚本、只用原生 HTML 的文档,健壮几乎自动成立,不必为此叠 ARIA。
怎么落地
- 能用原生控件就不要自绘;自绘则按已有模式补齐名称、角色、状态,并保证状态变化写回树,而不是只改外观。
- 不要用 CSS 生成的伪文本充当唯一名称来源;树上要有真节点。
- 验证:检查器里每个可交互项都能读到 Name、Role、State;再用 NVDA+Firefox、JAWS+Chrome、VoiceOver+Safari 各走一遍关键路径。只在一套组合里活着的步骤,按未解析处理,而不是按「个别用户环境问题」关掉。