先记住这个答案
:indeterminate 匹配处于「不确定」状态的表单控件。对复选框来说,它的意思是「既不是选中也不是未选中」,视觉上显示为一个横杠而不是勾。这个状态只能通过 JavaScript 设置 checkbox.indeterminate = true,没有对应的 HTML 属性。除了复选框,同名单选按钮组里没有任何一个被选中时,以及没有 value 属性的 <progress> 元素,也会匹配 :indeterminate。
- 复选框半选需要 JS 设置
- 没有对应的 HTML 属性
- 单选按钮组未选时也匹配
<progress>没有value时也匹配
最常见的场景:全选按钮的半选状态
表格里经常有一个「全选」复选框。当列表中只选了一部分时,全选框既不该显示为「全选」也不该显示为「全不选」,这时就用半选状态来表示「部分选中」。
/* 半选状态加灰色背景 */
input[type="checkbox"]:indeterminate {
opacity: 0.6;
}
/* 选中状态正常显示 */
input[type="checkbox"]:checked {
opacity: 1;
}CSS 只管样式,真正触发半选状态需要 JavaScript。在列表的选中数量变化时判断:全选了就 selectAll.checked = true,一个没选就 selectAll.checked = false,选了一部分就 selectAll.indeterminate = true。
单选按钮组的不确定状态
同名的一组单选按钮(name 属性相同),如果页面加载时没有任何一个预设了 checked,那这组里的每个单选按钮都会匹配 :indeterminate。一旦用户选择了任何一个,整组的 :indeterminate 就全部失效,因为这时有了明确的选中项。
这在表单验证场景里很有用。比如用户必须选择一个选项才能继续,可以用 :indeterminate 给这组单选按钮加一个提示样式,告诉用户「这里还没选」。
- progress 元素的加载中状态
<progress>标签没有设置value属性时也匹配:indeterminate,浏览器通常会把它显示为一个来回滚动的条形动画,表示「正在加载但不知道进度」。给这种状态的进度条自定义样式,就可以用progress:indeterminate。
容易答错的地方
- 以为有 HTML 属性能设置 indeterminate
- 没有。HTML 里写
<input type="checkbox" indeterminate>是无效的,浏览器不认这个属性。只能通过 JavaScript 的element.indeterminate = true来设置。这和checked属性不同,checked既有 HTML 属性也有 JS 属性。 - 以为 indeterminate 影响 checked 的值
indeterminate是纯视觉状态,不影响checked属性的值。一个复选框可以同时checked = true和indeterminate = true,这时视觉上显示半选横杠,但提交表单时按checked = true算。用户点击一次后,indeterminate自动变成false,不管之前checked是什么。
面试官还会怎么问?
用户点击半选状态的复选框后会变成什么?
变成普通的选中状态。浏览器会把 indeterminate 设为 false,checked 变为 true。再次点击就变成未选中。半选状态只能通过 JavaScript 重新设置,用户的点击操作不会恢复它。
怎么统一不同浏览器上半选复选框的样式?
不同浏览器的默认半选样式差别很大。想统一外观,最常见的做法是用 appearance: none 去掉原生样式,然后用 ::before 伪元素和 CSS 画一个横杠。或者用自定义图标替代原生复选框。
indeterminate 和 aria-checked="mixed" 有什么关系?
aria-checked="mixed" 是可访问性属性,告诉屏幕阅读器这个复选框处于混合状态。:indeterminate 是 CSS 伪类,控制视觉样式。两者应该同步使用:设置 indeterminate = true 的同时设置 aria-checked="mixed",让视觉和语义一致。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。