aria-readonly仅是语义标记,不阻止用户操作;真正只读需用原生readonly属性;仅当元素不支持readonly但需向屏幕阅读器传达状态时才必须使用aria-readonly。

aria-readonly 不能单独声明只读行为
它只是个语义标记,不阻止任何用户操作。你写 aria-readonly="true",input 照样能输、能粘贴、能删,表单照样提交值——屏幕阅读器只会多读一句“只读”,而用户看到的和交互的,完全没变。
真正起效的只读必须靠原生 readonly 属性(对 <input type="text">、<textarea></textarea> 等有效),aria-readonly 只是辅助技术的“翻译员”,不是“执行者”。
什么时候必须加 aria-readonly="true"
仅当元素本身不支持 readonly,但又需要向屏幕阅读器传达只读状态时才用:
- 自定义控件:比如
<div role="textbox" contenteditable="false">,必须配 <code>aria-readonly="true",否则读屏可能默认当作可编辑 - 富文本编辑器(如 TinyMCE)切换只读模式后,需同步设置
aria-readonly="true",否则 NVDA/JAWS 不会播报状态变化 - 原生
<input>或<textarea></textarea>已设readonly,此时再加aria-readonly是冗余的,除非你在 JS 中动态切换readonly且想显式同步语义 -
readonly控制行为(禁输入、可聚焦、值提交),aria-readonly只管语义(告诉读屏“这是只读”) - 两者值不一致时(比如
readonly为 false,aria-readonly="true"),会造成“说一套做一套”——读屏说“只读”,用户却能改,违反 WCAG 4.1.2(名称、角色、值) - React/Vue 中若只绑定
readOnly={false}却忘了同步移除aria-readonly,就会出现这种错位 - 启用只读:
el.readOnly = true+el.setAttribute('aria-readonly', 'true') - 取消只读:
el.readOnly = false+el.removeAttribute('aria-readonly') - 判断状态时,永远用
el.readOnly(布尔值),而不是el.getAttribute('aria-readonly')—— 后者返回字符串或 null,不可靠 - 对非原生表单元素(如
<div role="spinbutton">),必须用 <code>aria-readonly,且需 JS 拦截keydown、paste等事件,否则“只读”纯属摆设 真正容易被忽略的是:aria-readonly 不解决任何交互问题,它只解决“读屏能不能正确理解”这一个问题。如果你没同步处理键盘输入、粘贴、鼠标双击选中等行为,那这个属性就只是在给辅助技术讲一个没人信的谎。
aria-readonly 和 readonly 同时写会怎样
不会报错,但容易埋坑:
JS 动态控制 aria-readonly 的正确姿势
别直接用 setAttribute 或字符串赋值,要配合真实状态同步更新:











