错误提示需要通过无障碍属性关联到对应字段
别名: aria-describedby 错误 · aria-invalid · error accessible description
概念解释
字段旁边画出一句红字,视力用户能对上。阅读器进入该字段时,若错误句子没有成为这个控件的描述,听见的只是名称和「编辑框」。用无障碍属性关联指错误文本有稳定 id,字段用 aria-describedby(或等价)指向它,并在无效时暴露无效状态。顶部清单、焦点移动、不只靠颜色,都不代替这层绑定。标签关联的是名称;这里关联的是当前错误描述。
机制
可访问描述是进入控件时附带朗读的第二句。没有这句,原因只存在于视觉布局里。人要离开字段去「读附近」才能听到错误,而填写模式不会四处走。第二层是描述列表会拼在一起:字段若已经用 describedby 挂了格式帮助,错误必须追加到同一条链,而不是换掉帮助或另挂一个阅读器找不到的节点。错误消失时要从链上拿掉,并撤掉无效状态,否则会把过期原因当成当前描述。aria-invalid 不携带原因,只携带「现在无效」;原因在描述里。两者缺一,阅读器要么不报无效,要么报无效但说不出改什么。
怎么研究
提交出错误后,用阅读器只进入字段(不读页顶清单),记录能否听到原因和无效状态。比较「仅视觉红字」「describedby 指向错误」「错误只在 live 区域里播一次」。
自变量:是否 describedby、是否 aria-invalid、帮助文本与错误是否共链、错误解除后属性是否更新。
因变量:进入字段时是否听到原因、是否听到过期原因、只播一次之后再进入是否还能听到。
live 区域的一次性播报不能代替进入字段时的描述——人会在改的过程中反复进出。自动化可检查属性在不在,听测才能确认读的是哪一句。
边界
自定义下拉、画布里的错不能挂在原生 input 上,要把描述挂到实际接收焦点的那个角色节点。多条错误(格式 + 必填)应合成一句描述,避免朗读两段互相矛盾的话。语言切换后错误节点的 id 还在、文本变了,绑定可以不改;若错误节点被销毁重建,必须重写 describedby。打印没有这些属性。
怎么落地
- 每个字段级错误文本给稳定 id,无效时字段
aria-describedby包含该 id,并设无效状态。 - 已有帮助描述时,把错误 id 加进同一条
describedby列表,不要覆盖帮助。 - 值合法后同时去掉错误 id 与无效状态,避免朗读旧原因。
- 验证:阅读器进入无效字段,确认听到名称、无效、原因。改合法后再进入,确认原因已不在。打开无障碍树,看描述指向的节点就是屏幕上那句红字。把错误只放进一次 live 播报、不挂 describedby,作为不得通过的对照。