不同阅读器与浏览器组合行为不同
别名: 阅读器组合 · AT 组合 · 引擎差异
概念解释
同一页在 VoiceOver+Safari 上能用,搬到 JAWS+Chrome 可能不报角色,搬到 NVDA+Firefox 可能多报一层。用户真正运行的不是「阅读器」或「浏览器」,而是一对组合。组合不同,同一棵树会被翻译成不同的句子和不同的可操作行为。
机制
浏览器负责把页面收成无障碍树;阅读器负责把树收成语音、盲文和快捷键。两边各有一份映射表,而且独立升级。角色怎么报、属性认不认、动态变化会不会响,是两份表相乘的结果。作者看见的「我这页是对的」,往往只是自己那一对组合下的投影。
差异不是边角。有的引擎把自定义角色降成组,有的会报;有的认某一类状态,有的忽略。所以「在我的 Mac 上测过阅读器」只证明这一对组合,证明不了用户手里的那一对。失败可能出在页面,也可能出在这对组合的映射缝里——要靠第二对组合才能分开。
怎么研究
固定页面,换组合:NVDA+Firefox、JAWS+Chrome、VoiceOver+Safari,同一脚本(找到控件、听一句、激活、听状态)。把播报原文记下来,按「类型 / 名称 / 状态 / 能否激活」对齐。
自变量:阅读器、浏览器、二者组合。 因变量:播报是否含三个槽位、激活是否成功、同一操作在组合间是否一致。
差异出现时,换浏览器留阅读器、换阅读器留浏览器,看缝在哪一侧。不要把单一组合的通过写成「辅助技术兼容」。
边界
原生 App 走系统辅助功能 API,不经过浏览器,网页上的组合差异搬不过去;但 iOS VoiceOver 和 macOS VoiceOver 仍不是同一运行时。企业内部若能限定员工只用一对组合,测试面可以收窄,对外产品不行。极新或极旧的版本会放大差异,抽样应落在用户实际版本,而不是实验室里的最新 nightly。
怎么落地
- 把「阅读器×浏览器」当成测试单元,不要只记阅读器名字。
- 主流程至少在两对彼此独立的组合上走通,一对通过不能签收。
- 验证:同一任务在 NVDA+Firefox 与 VoiceOver+Safari 上各做一遍,把两句播报和两次激活并排。只在其中一对成立的行为,还不是这条产品的行为。