---
title: Checkbox Group
subtitle: Provides shared state to a series of checkboxes.
description: A high-quality, unstyled React checkbox group component that provides a shared state for a series of checkboxes.
---

# Checkbox Group

A high-quality, unstyled React checkbox group component that provides a shared state for a series of checkboxes.

## Demo

### Tailwind

This example shows how to implement the component using Tailwind CSS.

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { Checkbox } from '@base-ui/react/checkbox';
import { CheckboxGroup } from '@base-ui/react/checkbox-group';

export default function ExampleCheckboxGroup() {
  const id = React.useId();
  return (
    <CheckboxGroup
      aria-labelledby={id}
      defaultValue={['fuji-apple']}
      className="flex flex-col items-start gap-1 text-gray-900"
    >
      <div className="font-medium" id={id}>
        Apples
      </div>

      <label className="flex items-center gap-2">
        <Checkbox.Root
          name="apple"
          value="fuji-apple"
          className="flex size-5 items-center justify-center rounded-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-800 data-[checked]:bg-gray-900 data-[unchecked]:border data-[unchecked]:border-gray-300"
        >
          <Checkbox.Indicator className="flex text-gray-50 data-[unchecked]:hidden">
            <CheckIcon className="size-3" />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Fuji
      </label>

      <label className="flex items-center gap-2">
        <Checkbox.Root
          name="apple"
          value="gala-apple"
          className="flex size-5 items-center justify-center rounded-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-800 data-[checked]:bg-gray-900 data-[unchecked]:border data-[unchecked]:border-gray-300"
        >
          <Checkbox.Indicator className="flex text-gray-50 data-[unchecked]:hidden">
            <CheckIcon className="size-3" />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Gala
      </label>

      <label className="flex items-center gap-2">
        <Checkbox.Root
          name="apple"
          value="granny-smith-apple"
          className="flex size-5 items-center justify-center rounded-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-800 data-[checked]:bg-gray-900 data-[unchecked]:border data-[unchecked]:border-gray-300"
        >
          <Checkbox.Indicator className="flex text-gray-50 data-[unchecked]:hidden">
            <CheckIcon className="size-3" />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Granny Smith
      </label>
    </CheckboxGroup>
  );
}

function CheckIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg fill="currentcolor" width="10" height="10" viewBox="0 0 10 10" {...props}>
      <path d="M9.1603 1.12218C9.50684 1.34873 9.60427 1.81354 9.37792 2.16038L5.13603 8.66012C5.01614 8.8438 4.82192 8.96576 4.60451 8.99384C4.3871 9.02194 4.1683 8.95335 4.00574 8.80615L1.24664 6.30769C0.939709 6.02975 0.916013 5.55541 1.19372 5.24822C1.47142 4.94102 1.94536 4.91731 2.2523 5.19524L4.36085 7.10461L8.12299 1.33999C8.34934 0.993152 8.81376 0.895638 9.1603 1.12218Z" />
    </svg>
  );
}
```

### CSS Modules

This example shows how to implement the component using CSS Modules.

```css
/* index.module.css */
.CheckboxGroup {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 0.25rem;
  color: var(--color-gray-900);
}

.Caption {
  font-weight: 500;
}

.Item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.Checkbox {
  box-sizing: border-box;
  display: flex;
  width: 1.25rem;
  height: 1.25rem;
  align-items: center;
  justify-content: center;
  border-radius: 0.25rem;
  outline: 0;
  padding: 0;
  margin: 0;
  border: none;

  &[data-unchecked] {
    border: 1px solid var(--color-gray-300);
    background-color: transparent;
  }

  &[data-checked] {
    background-color: var(--color-gray-900);
  }

  &:focus-visible {
    outline: 2px solid var(--color-blue);
    outline-offset: 2px;
  }
}

.Indicator {
  display: flex;
  color: var(--color-gray-50);

  &[data-unchecked] {
    display: none;
  }
}

.Icon {
  width: 0.75rem;
  height: 0.75rem;
}
```

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { Checkbox } from '@base-ui/react/checkbox';
import { CheckboxGroup } from '@base-ui/react/checkbox-group';
import styles from './index.module.css';

export default function ExampleCheckboxGroup() {
  const id = React.useId();
  return (
    <CheckboxGroup
      aria-labelledby={id}
      defaultValue={['fuji-apple']}
      className={styles.CheckboxGroup}
    >
      <div className={styles.Caption} id={id}>
        Apples
      </div>

      <label className={styles.Item}>
        <Checkbox.Root name="apple" value="fuji-apple" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Fuji
      </label>

      <label className={styles.Item}>
        <Checkbox.Root name="apple" value="gala-apple" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Gala
      </label>

      <label className={styles.Item}>
        <Checkbox.Root name="apple" value="granny-smith-apple" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Granny Smith
      </label>
    </CheckboxGroup>
  );
}

function CheckIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg fill="currentcolor" width="10" height="10" viewBox="0 0 10 10" {...props}>
      <path d="M9.1603 1.12218C9.50684 1.34873 9.60427 1.81354 9.37792 2.16038L5.13603 8.66012C5.01614 8.8438 4.82192 8.96576 4.60451 8.99384C4.3871 9.02194 4.1683 8.95335 4.00574 8.80615L1.24664 6.30769C0.939709 6.02975 0.916013 5.55541 1.19372 5.24822C1.47142 4.94102 1.94536 4.91731 2.2523 5.19524L4.36085 7.10461L8.12299 1.33999C8.34934 0.993152 8.81376 0.895638 9.1603 1.12218Z" />
    </svg>
  );
}
```

## Usage guidelines

- **Form controls must have an accessible name**: It can be created using `<label>` elements, or the `Field` and `Fieldset` components. See [Labeling a checkbox group](/react/components/checkbox-group.md) and the [forms guide](/react/handbook/forms.md).

## Anatomy

Checkbox Group is composed together with [Checkbox](/react/components/checkbox.md). Import the components and place them together:

```jsx title="Anatomy"
import { Checkbox } from '@base-ui/react/checkbox';
import { CheckboxGroup } from '@base-ui/react/checkbox-group';

<CheckboxGroup>
  <Checkbox.Root />
</CheckboxGroup>;
```

## Examples

### Labeling a checkbox group

A visible label for the group is created by specifying `aria-labelledby` on `<CheckboxGroup>` to reference the `id` of a sibling element that contains the group label text.

```tsx title="Using aria-labelledby to label a checkbox group"
<div id="protocols-label">Allowed network protocols</div>
<CheckboxGroup aria-labelledby="protocols-label">{/* ... */}</CheckboxGroup>
```

For individual checkboxes, use an enclosing `<label>` element that wraps each `<Checkbox.Root>`. An enclosing label is announced to screen readers when focus is on the control, and ensures that clicking on any gaps between the label and checkbox still toggles it.

```tsx title="Using an enclosing label to label a checkbox" {1,4}
<label>
  <Checkbox.Root value="http" />
  HTTP
</label>
```

The [Field](/react/components/field.md) and [Fieldset](/react/components/fieldset.md) components eliminate the need to track `id` or `aria-labelledby` associations manually. They support both enclosing and sibling labeling patterns, along with a UX improvement to prevent double clicks from selecting the label text.

1. **Group label**: Since the group contains multiple controls, it can be labeled as a fieldset. Use [Fieldset](/react/components/fieldset.md) by replacing the `<Fieldset.Root>` element with `<CheckboxGroup>` via the `render` prop. `<Fieldset.Legend>` provides the visible label for the group.
2. **Individual label**: Place each individual checkbox in `<Field.Item>`, then label it using an enclosing `<Field.Label>`. Enclosing labels ensure that clicking on any gaps between the label and checkbox still toggles it.

```tsx title="Using Field and Fieldset to label a checkbox group"
<Field.Root>
  <Fieldset.Root render={<CheckboxGroup />}>
    <Fieldset.Legend>Allowed network protocols</Fieldset.Legend>
    <Field.Item>
      <Field.Label>
        <Checkbox.Root value="http" />
        HTTP
      </Field.Label>
    </Field.Item>
    <Field.Item>
      <Field.Label>
        <Checkbox.Root value="https" />
        HTTPS
      </Field.Label>
    </Field.Item>
    <Field.Item>
      <Field.Label>
        <Checkbox.Root value="ssh" />
        SSH
      </Field.Label>
    </Field.Item>
  </Fieldset.Root>
</Field.Root>
```

### Form integration

To use a checkbox group in a form, pass the checkbox group's `name` to `<Field.Root>`:

```tsx title="Using Checkbox Group in a form" {2}
<Form>
  <Field.Root name="allowedNetworkProtocols">
    <Fieldset.Root render={<CheckboxGroup />}>
      <Fieldset.Legend>Allowed network protocols</Fieldset.Legend>
      <Field.Item>
        <Field.Label>
          <Checkbox.Root value="http" />
          HTTP
        </Field.Label>
      </Field.Item>
      <Field.Item>
        <Field.Label>
          <Checkbox.Root value="https" />
          HTTPS
        </Field.Label>
      </Field.Item>
      <Field.Item>
        <Field.Label>
          <Checkbox.Root value="ssh" />
          SSH
        </Field.Label>
      </Field.Item>
    </Fieldset.Root>
  </Field.Root>
</Form>
```

### Parent checkbox

A checkbox that controls other checkboxes within a `<CheckboxGroup>` can be created:

1. Make `<CheckboxGroup>` a controlled component
2. Pass an array of all the child checkbox values to the `allValues` prop on the `<CheckboxGroup>` component
3. Add the `parent` boolean prop to the parent `<Checkbox.Root>`

## Demo

### CSS Modules

This example shows how to implement the component using CSS Modules.

```css
/* index.module.css */
.CheckboxGroup {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 0.25rem;
  color: var(--color-gray-900);
}

.Caption {
  font-weight: 500;
}

.Item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.Checkbox {
  box-sizing: border-box;
  display: flex;
  width: 1.25rem;
  height: 1.25rem;
  align-items: center;
  justify-content: center;
  border-radius: 0.25rem;
  outline: 0;
  padding: 0;
  margin: 0;
  border: none;

  &[data-unchecked] {
    border: 1px solid var(--color-gray-300);
    background-color: transparent;
  }

  &[data-checked] {
    background-color: var(--color-gray-900);
  }

  &[data-indeterminate] {
    border: 1px solid var(--color-gray-300);
    background-color: canvas;
  }

  &:focus-visible {
    outline: 2px solid var(--color-blue);
    outline-offset: 2px;
  }
}

.Indicator {
  display: flex;
  color: var(--color-gray-50);

  &[data-unchecked] {
    display: none;
  }

  &[data-indeterminate] {
    color: var(--color-gray-900);
  }
}

.Icon {
  width: 0.75rem;
  height: 0.75rem;
}
```

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { Checkbox } from '@base-ui/react/checkbox';
import { CheckboxGroup } from '@base-ui/react/checkbox-group';
import styles from './index.module.css';

const fruits = ['fuji-apple', 'gala-apple', 'granny-smith-apple'];

export default function ExampleCheckboxGroup() {
  const id = React.useId();
  const [value, setValue] = React.useState<string[]>([]);

  return (
    <CheckboxGroup
      aria-labelledby={id}
      value={value}
      onValueChange={setValue}
      allValues={fruits}
      className={styles.CheckboxGroup}
      style={{ marginLeft: '1rem' }}
    >
      <label className={styles.Item} id={id} style={{ marginLeft: '-1rem' }}>
        <Checkbox.Root className={styles.Checkbox} parent>
          <Checkbox.Indicator
            className={styles.Indicator}
            render={(props, state) => (
              <span {...props}>
                {state.indeterminate ? (
                  <HorizontalRuleIcon className={styles.Icon} />
                ) : (
                  <CheckIcon className={styles.Icon} />
                )}
              </span>
            )}
          />
        </Checkbox.Root>
        Apples
      </label>

      <label className={styles.Item}>
        <Checkbox.Root value="fuji-apple" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Fuji
      </label>

      <label className={styles.Item}>
        <Checkbox.Root value="gala-apple" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Gala
      </label>

      <label className={styles.Item}>
        <Checkbox.Root value="granny-smith-apple" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Granny Smith
      </label>
    </CheckboxGroup>
  );
}

function CheckIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg fill="currentcolor" width="10" height="10" viewBox="0 0 10 10" {...props}>
      <path d="M9.1603 1.12218C9.50684 1.34873 9.60427 1.81354 9.37792 2.16038L5.13603 8.66012C5.01614 8.8438 4.82192 8.96576 4.60451 8.99384C4.3871 9.02194 4.1683 8.95335 4.00574 8.80615L1.24664 6.30769C0.939709 6.02975 0.916013 5.55541 1.19372 5.24822C1.47142 4.94102 1.94536 4.91731 2.2523 5.19524L4.36085 7.10461L8.12299 1.33999C8.34934 0.993152 8.81376 0.895638 9.1603 1.12218Z" />
    </svg>
  );
}

function HorizontalRuleIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg
      width="10"
      height="10"
      viewBox="0 0 24 24"
      fill="currentcolor"
      xmlns="http://www.w3.org/2000/svg"
      {...props}
    >
      <line
        x1="3"
        y1="12"
        x2="21"
        y2="12"
        stroke="currentColor"
        strokeWidth={3}
        strokeLinecap="round"
      />
    </svg>
  );
}
```

### Nested parent checkbox

## Demo

### CSS Modules

This example shows how to implement the component using CSS Modules.

```css
/* index.module.css */
.CheckboxGroup {
  display: flex;
  flex-direction: column;
  align-items: start;
  gap: 0.25rem;
  color: var(--color-gray-900);
}

.Caption {
  font-weight: 500;
}

.Item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.Checkbox {
  box-sizing: border-box;
  display: flex;
  width: 1.25rem;
  height: 1.25rem;
  align-items: center;
  justify-content: center;
  border-radius: 0.25rem;
  outline: 0;
  padding: 0;
  margin: 0;
  border: none;

  &[data-unchecked] {
    border: 1px solid var(--color-gray-300);
    background-color: transparent;
  }

  &[data-checked] {
    background-color: var(--color-gray-900);
  }

  &[data-indeterminate] {
    border: 1px solid var(--color-gray-300);
    background-color: canvas;
  }

  &:focus-visible {
    outline: 2px solid var(--color-blue);
    outline-offset: 2px;
  }
}

.Indicator {
  display: flex;
  color: var(--color-gray-50);

  &[data-unchecked] {
    display: none;
  }

  &[data-indeterminate] {
    color: var(--color-gray-900);
  }
}

.Icon {
  width: 0.75rem;
  height: 0.75rem;
}
```

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { Checkbox } from '@base-ui/react/checkbox';
import { CheckboxGroup } from '@base-ui/react/checkbox-group';
import styles from './index.module.css';

const mainPermissions = ['view-dashboard', 'manage-users', 'access-reports'];
const userManagementPermissions = ['create-user', 'edit-user', 'delete-user', 'assign-roles'];

export default function PermissionsForm() {
  const id = React.useId();
  const [mainValue, setMainValue] = React.useState<string[]>([]);
  const [managementValue, setManagementValue] = React.useState<string[]>([]);

  return (
    <CheckboxGroup
      aria-labelledby={id}
      value={mainValue}
      onValueChange={(value) => {
        if (value.includes('manage-users')) {
          setManagementValue(userManagementPermissions);
        } else if (managementValue.length === userManagementPermissions.length) {
          setManagementValue([]);
        }
        setMainValue(value);
      }}
      allValues={mainPermissions}
      className={styles.CheckboxGroup}
      style={{ marginLeft: '1rem' }}
    >
      <label className={styles.Item} id={id} style={{ marginLeft: '-1rem' }}>
        <Checkbox.Root
          className={styles.Checkbox}
          parent
          indeterminate={
            managementValue.length > 0 &&
            managementValue.length !== userManagementPermissions.length
          }
        >
          <Checkbox.Indicator
            className={styles.Indicator}
            render={(props, state) => (
              <span {...props}>
                {state.indeterminate ? (
                  <HorizontalRuleIcon className={styles.Icon} />
                ) : (
                  <CheckIcon className={styles.Icon} />
                )}
              </span>
            )}
          />
        </Checkbox.Root>
        User Permissions
      </label>

      <label className={styles.Item}>
        <Checkbox.Root value="view-dashboard" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        View Dashboard
      </label>

      <label className={styles.Item}>
        <Checkbox.Root value="access-reports" className={styles.Checkbox}>
          <Checkbox.Indicator className={styles.Indicator}>
            <CheckIcon className={styles.Icon} />
          </Checkbox.Indicator>
        </Checkbox.Root>
        Access Reports
      </label>

      <CheckboxGroup
        aria-labelledby="manage-users-caption"
        className={styles.CheckboxGroup}
        value={managementValue}
        onValueChange={(value) => {
          if (value.length === userManagementPermissions.length) {
            setMainValue((prev) => Array.from(new Set([...prev, 'manage-users'])));
          } else {
            setMainValue((prev) => prev.filter((v) => v !== 'manage-users'));
          }
          setManagementValue(value);
        }}
        allValues={userManagementPermissions}
        style={{ marginLeft: '1rem' }}
      >
        <label className={styles.Item} id="manage-users-caption" style={{ marginLeft: '-1rem' }}>
          <Checkbox.Root className={styles.Checkbox} parent>
            <Checkbox.Indicator
              className={styles.Indicator}
              render={(props, state) => (
                <span {...props}>
                  {state.indeterminate ? (
                    <HorizontalRuleIcon className={styles.Icon} />
                  ) : (
                    <CheckIcon className={styles.Icon} />
                  )}
                </span>
              )}
            />
          </Checkbox.Root>
          Manage Users
        </label>

        <label className={styles.Item}>
          <Checkbox.Root value="create-user" className={styles.Checkbox}>
            <Checkbox.Indicator className={styles.Indicator}>
              <CheckIcon className={styles.Icon} />
            </Checkbox.Indicator>
          </Checkbox.Root>
          Create User
        </label>

        <label className={styles.Item}>
          <Checkbox.Root value="edit-user" className={styles.Checkbox}>
            <Checkbox.Indicator className={styles.Indicator}>
              <CheckIcon className={styles.Icon} />
            </Checkbox.Indicator>
          </Checkbox.Root>
          Edit User
        </label>

        <label className={styles.Item}>
          <Checkbox.Root value="delete-user" className={styles.Checkbox}>
            <Checkbox.Indicator className={styles.Indicator}>
              <CheckIcon className={styles.Icon} />
            </Checkbox.Indicator>
          </Checkbox.Root>
          Delete User
        </label>

        <label className={styles.Item}>
          <Checkbox.Root value="assign-roles" className={styles.Checkbox}>
            <Checkbox.Indicator className={styles.Indicator}>
              <CheckIcon className={styles.Icon} />
            </Checkbox.Indicator>
          </Checkbox.Root>
          Assign Roles
        </label>
      </CheckboxGroup>
    </CheckboxGroup>
  );
}

function CheckIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg fill="currentcolor" width="10" height="10" viewBox="0 0 10 10" {...props}>
      <path d="M9.1603 1.12218C9.50684 1.34873 9.60427 1.81354 9.37792 2.16038L5.13603 8.66012C5.01614 8.8438 4.82192 8.96576 4.60451 8.99384C4.3871 9.02194 4.1683 8.95335 4.00574 8.80615L1.24664 6.30769C0.939709 6.02975 0.916013 5.55541 1.19372 5.24822C1.47142 4.94102 1.94536 4.91731 2.2523 5.19524L4.36085 7.10461L8.12299 1.33999C8.34934 0.993152 8.81376 0.895638 9.1603 1.12218Z" />
    </svg>
  );
}

function HorizontalRuleIcon(props: React.ComponentProps<'svg'>) {
  return (
    <svg
      width="10"
      height="10"
      viewBox="0 0 24 24"
      fill="currentcolor"
      xmlns="http://www.w3.org/2000/svg"
      {...props}
    >
      <line
        x1="3"
        y1="12"
        x2="21"
        y2="12"
        stroke="currentColor"
        strokeWidth={3}
        strokeLinecap="round"
      />
    </svg>
  );
}
```

## API reference

Provides a shared state to a series of checkboxes.

**CheckboxGroup Props:**

| Prop          | Type                                                                               | Default | Description                                                                                                                                                                                  |
| :------------ | :--------------------------------------------------------------------------------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| defaultValue  | `string[]`                                                                         | -       | Names of the checkboxes in the group that should be initially ticked.To render a controlled checkbox group, use the `value` prop instead.                                                    |
| value         | `string[]`                                                                         | -       | Names of the checkboxes in the group that should be ticked.To render an uncontrolled checkbox group, use the `defaultValue` prop instead.                                                    |
| onValueChange | `((value: string[], eventDetails: CheckboxGroupChangeEventDetails) => void)`       | -       | Event handler called when a checkbox in the group is ticked or unticked.&#xA;Provides the new value as an argument.                                                                          |
| allValues     | `string[]`                                                                         | -       | Names of all checkboxes in the group. Use this when creating a parent checkbox.                                                                                                              |
| disabled      | `boolean`                                                                          | `false` | Whether the component should ignore user interaction.                                                                                                                                        |
| className     | `string \| ((state: CheckboxGroup.State) => string \| undefined)`                  | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component’s state.                                                                                     |
| style         | `CSSProperties \| ((state: CheckboxGroup.State) => CSSProperties \| undefined)`    | -       | -                                                                                                                                                                                            |
| render        | `ReactElement \| ((props: HTMLProps, state: CheckboxGroup.State) => ReactElement)` | -       | Allows you to replace the component’s HTML element&#xA;with a different tag, or compose it with another component.Accepts a `ReactElement` or a function that returns the element to render. |

**CheckboxGroup Data Attributes:**

| Attribute     | Type | Description                                  |
| :------------ | :--- | :------------------------------------------- |
| data-disabled | -    | Present when the checkbox group is disabled. |
