aria-invalid="true"必须配合aria-describedby指向的错误提示元素ID才能被屏幕阅读器读出具体错误原因,单独设置仅播报“无效”。

aria-invalid必须配合aria-describedby才能被读出错误原因
单独写aria-invalid="true",屏幕阅读器只会读“无效”,不会读后面的错误文案——它只是个状态开关,不是内容指针。真正把错误文字和输入框关联起来的,是aria-describedby指向的id。
常见错误:只改了错误文案内容,但没同步设置aria-describedby;或者写了aria-describedby="error-msg",但页面里根本没有id="error-msg"的元素。
-
aria-describedby的值必须是字符串,且严格等于错误提示元素的id(不能带#号) - 错误提示元素建议加
role="alert"或aria-live="assertive",确保动态插入时能被主动播报 - 该元素不能用
display: none或aria-hidden="true"隐藏——哪怕DOM存在、ID匹配,也会被跳过 - 推荐用视觉隐藏类(如
visually-hidden)控制显隐,而不是删DOM或设display: none
JavaScript校验时必须手动同步设置aria-invalid和aria-describedby
浏览器原生校验(比如required、type="email")不会自动设置aria-invalid,也不会更新aria-describedby。这些属性全靠JS手动写入,漏掉任何一个环节,无障碍提示就断了。
典型踩坑场景:用户输入后JS判断失败,只做了errorEl.textContent = "邮箱格式不对",却忘了input.setAttribute('aria-invalid', 'true')和input.setAttribute('aria-describedby', 'email-error')。
- 校验失败时:设
aria-invalid="true"+aria-describedby="xxx" - 校验通过时:必须显式设
aria-invalid="false"(不能只removeAttribute),并清空aria-describedby或设为空字符串 - 异步校验(如用户名唯一性检查)完成前,不要提前设
aria-invalid="true",否则造成误报 - 多个字段联动校验(如密码确认)时,两个
input都要分别设置对应属性,不能只动一个
aria-invalid加错位置等于没加
aria-invalid必须加在表单控件本身上,也就是、、这些元素,加在包装容器、label或错误提示div上完全无效。
例如:是对的;而或都起不到任何作用。
- 值只能是字符串
"true"、"false",不能是布尔true或数字1 - 不要写
aria-invalid(无值)或aria-invalid="",行为不可靠 - 常规业务校验只用
"true"/"false","grammar"和"spelling"仅用于富文本编辑器场景 - 即使用了
aria-invalid="true",也要配CSS规则(如[aria-invalid="true"] { border-color: #d32f2f; })做视觉反馈
原生校验伪类:invalid和aria-invalid是两套独立机制
:invalid是CSS伪类,只响应浏览器原生验证逻辑;aria-invalid是ARIA属性,只影响辅助技术。两者不自动同步,也不能互相替代。
比如你写了,但没调用input.checkValidity(),那:invalid样式根本不会生效;而aria-invalid则压根不会被设上,除非你手动写JS。
- 触发
:invalid样式:必须调用input.checkValidity()(推荐在blur或input事件中) - 触发
aria-invalid播报:必须手动设置属性,并确保aria-describedby指向的元素可访问 - 拦截
submit事件后,仍需对每个字段调用checkValidity()来更新伪类,再手动同步ARIA属性 - 不要指望
setCustomValidity()会帮你设aria-invalid——它只管原生校验流,不管ARIA
实际项目中最容易被忽略的是:错误提示元素虽然DOM存在、ID也对得上,但因为用了display: none或visibility: hidden,导致屏幕阅读器完全跳过它。这种情况下,aria-invalid和aria-describedby都成了摆设。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











