aria-checked="mixed" 仅作语义标注,不自动触发三态行为,需配合 role="checkbox"、tabindex="0"、js 状态管理及对应视觉样式才能被读屏正确识别并实现完整可访问性。

aria-checked 不能直接用于三态 checkbox
原生 <input type="checkbox"> 只支持 true/false 两态,aria-checked 本身也只接受 "true"、"false" 或 "mixed" 三个字符串值,但它**不自动触发三态行为**——浏览器不会因为你设了 aria-checked="mixed" 就让复选框显示“半选”图标,也不会响应鼠标点击切换三态。它只是语义标注,必须搭配 JS 手动管理状态和视觉反馈。
怎么让 aria-checked="mixed" 被读屏识别
关键不是写对属性,而是确保整个结构符合 ARIA 角色规范:
-
role="checkbox"必须设在可交互元素上(比如<div> 或 <code><button></button>),不能套在容器上 -
tabindex="0"必须存在,否则键盘无法聚焦,读屏无法关联当前项 -
aria-checked值必须是字符串:"true"、"false"或"mixed"(注意引号,不能写成布尔值true) - 切换时,必须用 JS 同步更新
aria-checked,并调用element.focus()确保焦点到位
示例正确结构:
<div role="checkbox" tabindex="0" aria-checked="mixed" aria-label="全选(部分勾选)"> <span class="custom-checkbox-icon"></span> 全选 </div>
三态逻辑怎么用 JS 实现
三态本质是状态机:未选中 → 部分选中 → 全选 → 未选中(循环)。常见错误是只靠子项数量判断,忽略“取消全选后是否还有任意一项被选中”。
- 每次子项状态变化时,统计已选数量:
const checkedCount = items.filter(i => i.checked).length - 设为
"mixed"的条件是:checkedCount > 0 && checkedCount - 设为
"true"的条件是:checkedCount === items.length - 设为
"false"的条件是:checkedCount === 0 - 点击主控件时,不要直接 toggle,而是按当前
aria-checked值决定下一步:"false"→ 全选;"true"→ 全不选;"mixed"→ 全选(或按产品逻辑定)
样式和可访问性容易漏掉的点
很多人写了 aria-checked="mixed" 却发现读屏不报“混合状态”,问题往往出在:
- 用了
[aria-checked]CSS 选择器 —— 它会匹配所有带该属性的元素,包括"false",应明确写成[aria-checked="mixed"] - 没给
aria-checked="mixed"提供对应的视觉样式(比如中间横线、斜杠、或特殊图标),用户看不到状态差异 - 键盘操作只支持
Space,没处理Enter,或者没阻止默认行为导致页面跳转 - 用
click事件但没加e.preventDefault(),导致<button></button>触发表单提交
复杂点在于:三态不是 DOM 原生能力,它完全依赖 JS 状态同步 + ARIA 语义 + 视觉反馈三者严格对齐。少一个环节,读屏就可能静默,键盘用户就卡住,视觉用户就困惑。











