Menu

HTML 复选框:checked、value、分组与自定义样式

如何用 <input type="checkbox"> 在 HTML 中创建复选框:标签、checked 属性、勾选和未勾选时表单分别发送什么、复选框分组、用 indeterminate 状态实现全选,以及样式设置。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

如何在 HTML 中创建复选框

复选框就是 <input type="checkbox">。把它和它的文字一起放进 <label>,这样点击文字也能切换勾选状态。勾选其中一个或两个,再点击 Save,看看表单会发送什么:

在默认状态下,表单只发送 updates=on。原因可以归结为两条规则:

  • 勾选的复选框发送 name=value。 第二个复选框没有 value,所以它发送默认值 on。
  • 未勾选的复选框什么都不发送。 既不是 newsletter=no,也不是空值:数据里根本没有这个名字。

HTML 中的 checked 设置初始状态。和所有布尔属性一样,起作用的是它是否存在:checked="false" 仍然会勾选复选框。

复选框的属性

属性作用
name勾选时发送的键名
value勾选时发送的内容(默认是 on)
checked页面加载时就处于勾选状态
required勾选这个复选框之前,表单无法提交
disabled无法切换,也不会被发送

一组复选框

对于“可以任选几项”的情况,给每个复选框相同的 name 和不同的 value。把它们包在带 <legend> 的 <fieldset> 里,让这一组有个名称:

表单发送的是 topic=html 和 topic=css:同一个名字出现两次。大多数服务器框架都能把它读取为一个列表。PHP 是个例外:除非名字以方括号结尾,即 name="topic[]",否则它只保留最后一个。在 JavaScript 中,new FormData(form).getAll('topic') 会返回 ['html', 'css']。

未勾选时也发送一个值

当服务器需要一个明确的“否”时,就在复选框之前放一个同名的隐藏输入框。未勾选时只发送隐藏输入框的值;勾选时两个值都会发送,服务器取最后一个:

点击 Continue:在勾选条款复选框之前,表单拒绝提交,因为它是 required 的。勾选后,表单发送 marketing=no 和 terms=accepted;如果第一个复选框也勾选了,就发送 marketing=no、marketing=yes 和 terms=accepted。Rails 等框架生成的正是这种隐藏输入框加复选框的组合。依赖这种写法之前,先确认你的服务器如何读取重复的名字。

全选与 indeterminate 状态

复选框还有第三种外观,一条短横线,表示“部分勾选”。它只能通过 JavaScript 设置:box.indeterminate = true。当“全选”复选框控制的复选框中有一部分被勾选时,就会用到它:

indeterminate 只改变外观(以及屏幕阅读器的播报内容:“混合”或“部分选中”)。复选框在底层仍然只有勾选或未勾选两种状态,表单发送的也是这个状态。点击处于 indeterminate 状态的复选框会清除短横线并切换勾选状态。

用 change 事件响应复选框的变化,读取 box.checked 获取它的状态。切换复选框时,box.value 不会改变。

设置复选框样式

最快的改法是 accent-color,它会给原生复选框换颜色,同时保留它的所有行为。想要完全不同的外观,appearance: none 会去掉原生的绘制效果,让你可以像设置任何盒子一样设置这个输入框的样式:

自定义的复选框仍然是真正的复选框:点击或按空格键都能切换,会随表单发送,也会被播报为复选框。用 :checked 绘制勾选状态,并保留 :focus-visible 样式,因为去掉原生绘制后,除了你自己添加的,不会再有任何焦点环。

开关按钮

开关是一种表示“现在打开还是关闭”的复选框,而不是“是否包含这一项”。用 appearance: none 绘制它,并加上 role="switch",这样屏幕阅读器播报的是一个打开或关闭的开关,而不是一个已勾选的复选框:

inset-inline-start 从行的起始边开始放置滑块,所以在从右到左书写的页面上,开关会朝另一个方向滑动,这正是应有的效果。对于只能选一个的成组是否选项,请参阅 HTML 单选按钮。

常见错误

  • 以为未勾选的复选框会发送 false。 什么都不会发送。在服务器上把缺失的名字当作“关闭”处理,或者加上隐藏输入框。
  • checked="false"。 它仍然会勾选复选框。删掉这个属性。
  • 复选框没有 label,或者旁边的文字不是 <label>。这样小小的方框就成了唯一的点击区域,屏幕阅读器也只会播报“复选框”,没有名称。请参阅 HTML label。
  • 忘了写 value,结果一组复选框都发送 on,服务器无法区分它们。
  • 读取 box.value 来判断是否勾选。 请使用 box.checked。
  • 用复选框做“单选”。 那是单选按钮的用途。

常见问题

如何在 HTML 中创建复选框?

把 <input type="checkbox"> 放在 label 里:<label><input type="checkbox" name="terms" value="yes"> I agree</label>。label 让文字也可以点击。

如何让复选框默认处于勾选状态?

加上 checked 属性:<input type="checkbox" name="news" checked>。起作用的是它是否存在,所以 checked="false" 仍然会勾选。在 JavaScript 中,设置 box.checked = true 或 false。

未勾选的复选框会发送什么值?

什么都不发送。未勾选的复选框会被完全排除在提交的数据之外。勾选的复选框会发送它的 value,如果没有 value,就发送 on。如果服务器需要一个明确的“否”,就在复选框之前放一个同名的隐藏输入框。

如何在 JavaScript 中获取复选框的值?

读取 box.checked,它的值是 true 或 false。box.value 是它将要发送的值,不管有没有勾选都保持不变。监听 change 事件,在复选框切换时做出响应。

如何修改复选框的颜色?

给它设置 accent-color:input[type=checkbox] { accent-color: #16a34a; }。想要完全自定义的外观,就设置 appearance: none,然后用 CSS 自己绘制方框和勾号。

Coddy 编程语言插图

和 Coddy 一起学编程

开始