aria-checked="mixed"是唯一合法的混合状态值,仅用于向辅助技术传递部分选中语义,不改变dom checked属性或表单提交行为,需配合js同步视觉样式与键盘交互。

aria-checked="mixed" 是唯一合法的混合状态值
浏览器和屏幕阅读器只认 aria-checked="mixed" 这个字符串,写成 aria-checked="true"、aria-checked="false" 或留空都不行。它不改变 DOM 的 checked 属性,也不影响表单提交——纯粹是给辅助技术传递“部分选中”语义的信号。
必须配合 JS 手动同步 aria-checked 和视觉样式
原生 <input type="checkbox"> 没有混合状态,所以得用自定义控件(比如 <div role="checkbox">)或隐藏原生框后用伪元素模拟。关键点:
<ul>
<li>不能只改 <code>aria-checked 属性,还得同步更新 CSS 类(如 .state-mixed)来切换 ✅ ➝ ⚪ 的视觉表现
aria-checked="true";全不选 → aria-checked="false";其余 → aria-checked="mixed"
aria-checked 值后端收不到 aria-checked,别指望它传数据
aria-checked 是纯语义层标记,不影响表单序列化。用户看到的“混合状态”只是 UI 提示,实际提交的仍是底层 <input> 的 checked 状态(true/false)或根本没提交(如果用了自定义 div)。常见处理方式:
- 保留一个隐藏的
<input type="hidden" name="xxx">,JS 在状态变化时写入 "all"/"none"/"partial" 字符串 - 或者直接用多个真实复选框 + 全选主控,靠后端解析选中项数量判断是否“部分”
- 千万别把
aria-checked当作服务端校验依据——它可能被绕过、被忽略、或压根没发过去
三态 checkbox 的 tabindex 和 keyboard 行为容易漏
如果用了 role="checkbox" 的自定义元素,必须手动加 tabindex="0" 才能获得焦点,否则键盘用户根本点不到。而且 change 事件不会自动触发,得监听 click 和 keydown(空格/Enter),再调用 event.preventDefault() 防止滚动,最后更新状态和 aria-checked。移动端还要考虑 touchstart 兼容性。











