Overview

Use a checkbox to let people select any number of items from a set, including none, such as pupils in a class, topics for a practice or rows in a results table.

Checkbox is the box on its own, with no label. In forms, use Checkbox Field, which adds a visible label and shows errors.

Checkbox states: unchecked, checked, indeterminate, error, disabled and focused

Anatomy

Checkbox anatomy, enlarged: an unchecked box with its hover halo and click area, and a checked box with its focus ring

#PartDescription
1Box16px (md) or 24px (lg). White, 1px grey-700 border, 4px corner radius. Fills primary-800 when checked.
2IndicatorA tick when checked, a dash when indeterminate. White.
3Hover haloA primary-300 circle behind the box on hover. 32px (md) or 40px (lg).
4Click areaInvisible, larger than the box: 40px (md) or 48px (lg).
5Focus ringA 2px white gap and a 2px primary-800 ring. Shows only when focused with the keyboard.

Use it when

  • People can select any number of items from a set, including none.
  • Each item sits in a row whose text names it, such as a table row, a list item or a tree node. For example, selecting pupils in a results table, choosing topics when creating a practice, or choosing classes and pupils when setting an assessment.
  • Filtering by several values at once, such as year groups in a trust dashboard filter.

Don't use it when

  • The checkbox needs its own label, as in a form. Use Checkbox Field.
  • People can pick only one option, such as one year group or one mark scheme. Use Radio Button.
  • The choice takes effect straight away, such as "Show answers to pupils". Use Switch.
  • Selecting it would run a command or open another window. A checkbox only records a choice; use a Button.

Size

  • md (default, 16px): dense desktop interfaces, such as filter dropdowns and settings lists.
  • lg (24px): pupil-facing screens, touch screens and table rows. Only lg meets the 44px minimum touch target.

Use the same size for every checkbox in a group.

md checkboxes in a year group filter and lg checkboxes in a pupil list

Indeterminate

Use checked="indeterminate" only on a "select all" checkbox or a parent row, when some but not all of its items are selected. Clicking it selects everything.

Never use indeterminate to mean "not sure" or "partly". It isn't an answer.

Try it: select some pupils, then use the select all checkbox.

const PupilSelection = () => {
  const pupils = ['Amara Okafor', 'Oliver Bennett', 'Priya Sharma']
  const [selected, setSelected] = React.useState(['Oliver Bennett'])
  const all = selected.length === pupils.length
  const some = selected.length > 0 && !all

  return (
    <div className="flex flex-col gap-3">
      <label className="flex gap-3 items-center">
        <Checkbox
          size="lg"
          checked={some ? 'indeterminate' : all}
          onCheckedChange={() => setSelected(all ? [] : pupils)}
        />
        <Text weight="bold">Select all pupils in 7A</Text>
      </label>
      {pupils.map((pupil) => (
        <label key={pupil} className="flex gap-3 items-center">
          <Checkbox
            size="lg"
            checked={selected.includes(pupil)}
            onCheckedChange={(value) =>
              setSelected(value ? [...selected, pupil] : selected.filter((p) => p !== pupil))
            }
          />
          <Text>{pupil}</Text>
        </label>
      ))}
    </div>
  )
}
render(<PupilSelection />)

Error

state="error" turns the border red. Always show an error message in text next to it; the red border alone isn't enough. Checkbox Field does this for you.

Two class checkboxes with red borders and the message "Select at least one class" below

Keyboard

Tab moves focus to the checkbox and Space ticks or unticks it. Enter does nothing, as for any checkbox. The focus ring shows only when focus comes from the keyboard.

A pupil table with the focus ring on the second row's checkbox

Accessibility

  • Give it a name. A bare checkbox has no visible label, so give it an aria-label that names the item, such as "Select Amara Okafor", or wrap it in a <label> with the row text.
  • Errors need text. Show an error message next to the checkbox, not only the red border.
  • Never rely on colour alone. Checked and indeterminate states use a tick or a dash as well as colour.
  • Use lg for touch. Only lg has a click area of at least 44px.

Do's and Don'ts

    Do

    Let teachers select several items from a list, such as pupils to set an assessment for.

    Don't

    Use checkboxes when only one option can be picked, such as a mark scheme. Use Radio Button instead.

    Do

    Use a select all checkbox in a table header. It goes indeterminate when only some rows are selected.

    Don't

    Use indeterminate to mean “not sure” or “partly”. It isn’t an answer.

    Do

    Use checkboxes for choices that are saved together with a button.

    Don't

    Use a checkbox for a setting that takes effect straight away. Use Switch instead.

    Do

    Use a button to run a command or open another page.

    Don't

    Use a checkbox to run a command or open another window.

    Do

    Show an error message in text next to the checkboxes.

    Don't

    Rely on the red border alone to show an error.

Structure and spacing

PropertyTokenpxrem
Box - mdsize-416px1
Box - lgsize-624px1.5
Border-1px-
Border radiusradius-sm4px0.25
Hover halo - md-32px2
Hover halo - lg-40px2.5
Click area - md-40px2.5
Click area - lg-48px3
Focus ring gapwhite2px0.125
Focus ringprimary-8002px0.125

Colour

StateBorderFillAtomQuest
Uncheckedgrey-700white#757575#757575
Checked, indeterminateprimary-800primary-800#0F67F5#16795B
Hover halo-primary-300#D6EAFF#BDEBD4
Errordangerwhite#F00505#F00505
Focus ringprimary-800-#0F67F5#16795B
Disabled30% opacity---

Options

OptionIn codeValuesDefault
Checkedchecked, defaultCheckedtrue, false, "indeterminate"Unchecked
Sizesizemd, lg. Can change by breakpoint.md
ErrorstateerrorNone
Disableddisabled30% opacity, not clickableEnabled
Namearia-labelText for screen readersNone

Related