R3.01.3DOM order as AT traversal order设计

结构顺序决定辅助技术的遍历顺序

别名: 源序即读序 · 无障碍树顺序 · source order is AT order

概念解释

辅助技术按结构顺序走界面:文档树、无障碍树里节点出现的先后,就是读屏线性读下去、键盘默认 Tab 下去的先后。用 CSS 把侧栏视觉上挪到右边、用绝对定位把按钮叠到卡片角落、用 order 把「下一步」画到最前,像素换了位置,树往往没换。看起来的从上到下,不必是辅助技术的从先到后。

实现约束在这里:要改遍历,改树;只改布局,遍历不动。视觉阅读路径可以另议,但辅助通道不会自动跟着 flex 和 grid 的视觉摆放走。

机制

读屏和默认 Tab 序消费的是无障碍树,而这棵树主要从源结构生成。定位、浮动、grid 放置、flex order 改的是绘制,多数情况下不重写树里的先后。于是出现两种顺序:眼睛按绘制走,辅助技术按源走。源里先写了侧栏再写主文,即使用户先看见主文,读屏仍先读完侧栏;源里「取消」在「确认」前面,即使确认按钮被画在左边,Tab 仍先落到取消。

把顺序交给绘制层,是把辅助通道绑在一套它读不到的坐标上。要对齐两条通道,只能让源结构的先后等于你希望被读到、被 Tab 到的先后。视觉重排是附加的绘制指令,不是遍历指令。

边界

有意做成的视觉与源不一致(例如桌面把导航画在左侧、源里却放在主内容之后以便先读正文)可以成立,但必须是写明的选择,并在辅助通道里验证,不能靠「看起来在左边」来假设先被读到。tabindex 大于 0 会把键盘序从源序里抽走,造成 Tab 与读屏线性序分叉,这是另一处断裂,不能用来「修正」视觉顺序。阴影 DOM、display: contents、部分浏览器对 flex order 是否影响 Tab 的处理并不统一,跨引擎不能假设绘制序会渗进树。空间导航(部分读屏按屏幕坐标跳)不是默认线性遍历,不能当实现已按视觉序走的证据。

怎么落地

  • 交付时同时给出源顺序:第一块被读到的是什么、主操作在树里相对取消/次要操作的位置;不要只给视觉画板。
  • 禁止用 flex order、负 margin、绝对定位去「把主操作挪到前面」而不改源里的位置。
  • 多栏、侧栏、粘性底栏先按希望被读到的顺序写进树,再用布局把它们画到视觉位置。
  • 验证:关掉样式或打开无障碍树查看器,记下节点先后;再用读屏线性读、用 Tab 走一遍。三份顺序应对得上设计声明的遍历。对不上的每一处,都是只改了绘制。

延伸

  • 同组R3.01.1 语义元素自带无障碍行为 · R3.01.2 用通用容器模拟控件需补全全部语义
  • 相邻J2.08 阅读顺序 · R3.09 语义化结构与可访问性实现
  • 站内检索DOM order · AT traversal · source order versus CSS order

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/R3.01.3