返回
UI · №18 · SPECIMEN

复选框Checkbox

复选框多选框勾选框不定态全选
LIVE SPECIMEN真的能玩,点点看

单个 Checkbox

多选分组

选择你感兴趣的领域(可多选)

全选 + 不定态

试试看

验证方式:

  • 点击区域:label 文字可点击(不只是小方框)
  • 键盘:Tab 聚焦到 Checkbox,Space 切换选中 / 未选
  • 不定态:在「全选任务」区域勾选部分任务,父级 Checkbox 显示横线(不定态)
  • 焦点环:Tab 浏览时所有 Checkbox 有可见焦点环(朱砂色 outline)

先看结论

用户从列表中选择多个选项(或单个可选项)的控件。可以多选(和 Radio 的"单选"相反)、随表单提交(和 Switch 的"立即生效"相对)、有三种视觉状态(未选 / 已选 / 不定态)。

适合
表单中的多选列表、单个可选项(接受协议)、全选场景(父级 Checkbox 用不定态表示"部分已选")。用户期望「勾选后随表单提交」,不是「拨一下立即生效」。
不适合
不要用 Checkbox 做立即生效的开关(用 Switch);不要用 Checkbox 做单选(用 Radio);不要在单个 Checkbox 上用不定态(那是全选场景专用);不要忘记关联 label(点击文字应该能勾选)。

直接发给 agent

Create a checkbox group for [options]. Requirements: - Use <input type="checkbox"> with unique id + <label for="..."> for each option - Style: * Unchecked: 16x16px square, 2px border Ink-2 (#6B675F), border-radius 2px * Checked: background Cinnabar (#C13E23), white checkmark icon (inline SVG) * Indeterminate: background Cinnabar, white minus icon (inline SVG) * Disabled: opacity 0.5, cursor not-allowed * Focus: 2px Cinnabar outline, offset 2px - Click area: label text is clickable (not just the box) - If "select all" is needed: * Parent checkbox shows indeterminate state when some (not all) children are checked * Clicking parent when indeterminate → check all * Clicking parent when all checked → uncheck all - Keyboard: Tab to focus, Space to toggle - Screen reader: announces "checkbox, [label], checked/unchecked/mixed"

技术标注5 项
语义标签
<input type="checkbox"> + <label>,label 的 for 属性关联 input id
键盘
Tab 可达;Space 切换选中 / 未选;Enter 不触发(那是提交表单)
不定态
只能通过 JS 设置 indeterminate=true,HTML 属性无法直接写
分组
多个 Checkbox 用 <fieldset> + <legend> 包裹,提供分组语义
可访问性
aria-checked(true/false/mixed);禁用时 disabled + aria-disabled=true

详细说明

复选框

它是什么

Checkbox 是用户从列表中选择多个选项(或单个可选项)的控件。

核心特征:

  • 可以多选(和 Radio 的“单选”相反)
  • 随表单提交(和 Switch 的“立即生效”相对)
  • 有三种视觉状态:未选 / 已选 / 不定态(后者只用于全选场景)

什么时候用 Checkbox? 见 №03「选择控件(怎么选)」词条的完整辨析。这个词条只讲 Checkbox 自己怎么做。

三种核心状态

状态 视觉 什么时候用
未选中 空心方框 用户未勾选此项
已选中 实心方框 + 白色对勾 用户已勾选此项
不定态 实心方框 + 白色横线 只用于全选场景:父级 Checkbox 表示“部分子项已选”

不定态(Indeterminate)的唯一用途

场景:邮件列表的「全选」Checkbox

邮件列表共 10 封:
  [ ] 全选         ← 父级 Checkbox,当前未选
  [ ] 邮件 1
  [ ] 邮件 2
  ...

用户勾选了 3 封:
  [−] 全选         ← 不定态(部分已选)
  [✓] 邮件 1
  [✓] 邮件 2
  [✓] 邮件 3
  [ ] 邮件 4
  ...

用户点击「全选」Checkbox:
  [✓] 全选         ← 从不定态变为全选
  [✓] 邮件 1
  [✓] 邮件 2
  ...全部勾上

不要在单个 Checkbox 上用不定态——那是「全选 / 部分选」场景专用的父级状态。

技术标注

考虑点 决策
HTML 结构 <input type="checkbox" id="..."> + <label for="...">,label 关联让文字可点
尺寸 Checkbox 本体 16x16px;label 文字 14-16px;整行最小点击区域 44px 高
对比度 边框 Ink-2 (#6B675F) 对比度 4.5+;选中态背景 Cinnabar (#C13E23) 对比度 5.28
不定态设置 只能通过 JS:checkbox.indeterminate = true,HTML 无此属性
分组 多个 Checkbox 用 <fieldset> + <legend> 包裹,提供语义分组
键盘 Tab 聚焦;Space 切换选中 / 未选;Enter 不触发(那是提交表单)
可访问性 aria-checked="true/false/mixed";禁用时 disabled + aria-disabled="true"

什么时候用这个词

做设计决策时

场景 1:单个可选项(接受协议)

表单底部有「我已阅读并同意服务条款」

用 Checkbox(不是 Switch):
  理由 1:这是表单的一部分,随提交一起发送
  理由 2:用户期望「勾选后点提交」,不是「拨一下立即生效」
  理由 3:视觉上 Checkbox 和表单其他输入框更协调

<label>
  <input type="checkbox" id="terms" required>
  我已阅读并同意<a href="/terms">服务条款</a>
</label>

场景 2:多选列表(兴趣标签)

注册时选择兴趣:
  [ ] 前端开发
  [ ] 后端开发
  [ ] 设计
  [ ] 产品

用户可以选 0 个、1 个或多个 → Checkbox
(如果是"只能选一个",那就该用 Radio)

<fieldset>
  <legend>选择你感兴趣的领域</legend>
  <label><input type="checkbox" name="interests" value="frontend"> 前端开发</label>
  <label><input type="checkbox" name="interests" value="backend"> 后端开发</label>
  <label><input type="checkbox" name="interests" value="design"> 设计</label>
  <label><input type="checkbox" name="interests" value="product"> 产品</label>
</fieldset>

场景 3:全选 + 不定态

邮件列表批量操作:

[−] 全选(当前选了 3 封)      ← 父级 Checkbox,不定态
  [✓] 邮件 1
  [✓] 邮件 2
  [✓] 邮件 3
  [ ] 邮件 4
  [ ] 邮件 5

交互逻辑:
  - 用户勾选任意子项 → 父级变不定态(如果不是全选)
  - 用户点不定态的父级 → 全选所有子项
  - 用户点全选态的父级 → 取消所有子项

JS 示例:
  parentCheckbox.indeterminate = (checkedCount > 0 && checkedCount < totalCount);
  parentCheckbox.checked = (checkedCount === totalCount);

给 agent 发指令时

设计一个任务管理应用的「任务列表」批量选择功能。

需求:
1. 列表顶部有「全选」Checkbox
2. 每个任务左侧有独立 Checkbox
3. 用户可以勾选多个任务后批量删除

交互要求:
- 勾选部分任务时,「全选」Checkbox 显示不定态(实心 + 横线)
- 点击不定态的「全选」→ 全部勾上
- 点击全选态的「全选」→ 全部取消
- 所有 Checkbox 支持键盘操作(Tab + Space)

样式要求(遵循 TellYourAgent 设计系统):
- Checkbox 尺寸 16x16px,圆角 2px
- 未选:2px 边框 Ink-2 (#6B675F)
- 已选 / 不定态:背景 Cinnabar (#C13E23),白色图标(对勾 / 横线)
- 禁用:opacity 0.5
- Focus:2px Cinnabar outline,offset 2px
- label 文字可点击(点击区域 = Checkbox + label 文字)

输出:HTML + CSS + JS(全选逻辑)+ 可访问性标注

常见错误

错误 1:label 和 input 没有关联

<!-- 错误 -->
<input type="checkbox" id="terms">
<label>我同意服务条款</label>

问题:点击文字不会勾选 Checkbox,用户只能点那个小方框(移动端很难点)

<!-- 正确 -->
<input type="checkbox" id="terms">
<label for="terms">我同意服务条款</label>

或者:
<label>
  <input type="checkbox">
  我同意服务条款
</label>

错误 2:在非全选场景用不定态

单个 Checkbox 显示不定态(横线)

用户困惑:这是选中还是没选中?

正确做法:不定态只用于「全选 Checkbox 表示部分子项已选」,
         单个 Checkbox 只有选中 / 未选两种状态。

错误 3:Checkbox 太小

Checkbox 只有 12x12px,label 文字紧贴着

问题:移动端用户点不中(手指触达区域推荐 ≥44px)

正确做法:
  - Checkbox 本体 16x16px
  - 整行(Checkbox + label)最小高度 44px
  - label 文字和 Checkbox 之间留 8-12px 间距

错误 4:只用颜色标记选中态

选中时只是边框变红,没有对勾图标

问题:色弱用户看不出选中 / 未选的区别

正确做法:选中态用「颜色 + 图标」双通道
  - 背景变 Cinnabar
  - 显示白色对勾

错误 5:禁用时没有视觉反馈

<input type="checkbox" disabled>

CSS 里没写 :disabled 样式,看起来和正常 Checkbox 一样

用户困惑:为什么点了没反应?

正确做法:
  input[type="checkbox"]:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }

相关词条

  • №03「选择控件(怎么选)」 — Switch vs Checkbox vs Radio 完整辨析(什么时候用哪个)
  • №03「表单结构与校验」 — Checkbox 作为表单字段的校验规则(必选 / 至少选 N 个)
  • №03「按钮怎么选」 — Checkbox 分组通常配合操作按钮(「删除选中项」用 Danger)
  • №04「表单验证提示」 — Checkbox 未勾选时的错误提示怎么显示

完整可复制的 Prompt

设计一个任务管理应用的「任务列表」,包含批量选择功能。

需求:
1. 列表顶部有「全选」Checkbox
2. 每个任务项左侧有独立 Checkbox
3. 列表底部有「删除选中项」按钮(Danger 变体)

HTML 结构:
- 用 <fieldset> + <legend> 包裹整个 Checkbox 分组
- 每个 Checkbox 用 <input type="checkbox"> + <label for="...">
- label 必须关联 input(点文字能勾选)

样式要求(遵循 TellYourAgent 设计系统):
- Checkbox 尺寸:16x16px,border-radius 2px
- 未选:2px 边框 Ink-2 (#6B675F),透明背景
- 已选:背景 Cinnabar (#C13E23),白色对勾(inline SVG)
- 不定态:背景 Cinnabar,白色横线(inline SVG)
- 禁用:opacity 0.5,cursor not-allowed
- Hover:边框变深(未选时)或背景变深(已选时)
- Focus:2px Cinnabar outline,offset 2px
- label 文字:14px,颜色 Ink (#1C1B18),与 Checkbox 间距 12px
- 整行最小高度:44px(移动端触达标准)

交互逻辑(JS):
1. 勾选任意子项:
   - 如果全部勾选 → 父级 checked=true, indeterminate=false
   - 如果部分勾选 → 父级 indeterminate=true
   - 如果全部未勾选 → 父级 checked=false, indeterminate=false

2. 点击父级「全选」:
   - 当前未选 → 全部勾上
   - 当前不定态 → 全部勾上
   - 当前全选 → 全部取消

3. 「删除选中项」按钮:
   - 没有选中项时 disabled
   - 有选中项时显示数量(「删除 3 项」)

可访问性:
- 每个 Checkbox 的 label 清晰描述选项内容
- 禁用时 aria-disabled="true"
- 父级 Checkbox 不定态时 aria-checked="mixed"
- 键盘操作:Tab 遍历,Space 切换选中 / 未选

响应式:
- 移动端(<768px):label 文字可以换行,保持 44px 最小点击高度
- 桌面端(≥768px):Checkbox 和 label 单行显示

输出:
- HTML(语义化结构)
- CSS(所有状态 + 响应式)
- JS(全选逻辑 + 按钮禁用逻辑)
- 可访问性标注(aria-* 属性说明)

为什么这个决策很重要

Checkbox 看起来很简单,但细节决定体验:

  • label 不关联 input → 移动端用户点不中,弃填
  • 不定态乱用 → 用户困惑「这是选中还是没选中」
  • 只用颜色标记 → 色弱用户分不出选中 / 未选
  • Checkbox 太小 → 触达区域不足,点击失败率高

一句话:Checkbox 的可用性,90% 取决于「label 能不能点」和「视觉反馈够不够清晰」。