Skip to main content
Since Shoelace 2.0 Code experimental Pattern stable Figma ready

Checkbox Group

<sl-checkbox-group> | SlCheckboxGroup

Checkbox groups are used to group multiple checkboxes so they function as a single form control.

Examples

Basic Checkbox Group

A basic checkbox group lays out multiple checkbox items vertically.

Initiate outbound transfers Approve outbound transfers Export transactions
<sl-checkbox-group label="Financial products permissions">
  <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox>
  <sl-checkbox value="approve-outbound" checked>Approve outbound transfers </sl-checkbox>
  <sl-checkbox value="export">Export transactions</sl-checkbox>
</sl-checkbox-group>
sl-checkbox-group label="Financial products permissions"
  sl-checkbox value="initiate-outbound" Initiate outbound transfers
  sl-checkbox value="approve-outbound" Approve outbound transfers
  sl-checkbox value="export" Export transactions
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';

const App = () => (
  <SlRadioGroup label="Select an option" name="a" value="1">
    <SlRadio value="1">Option 1</SlRadio>
    <SlRadio value="2">Option 2</SlRadio>
    <SlRadio value="3">Option 3</SlRadio>
  </SlRadioGroup>
);

Help Text

Add descriptive help text to a checkbox group with the help-text attribute. For help texts that contain HTML, use the help-text slot instead.

Initiate outbound transfers Approve outbound transfers Export transactions
<sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers">
  <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox>
  <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox>
  <sl-checkbox value="export">Export transactions</sl-checkbox>
</sl-checkbox-group>
sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers"
  sl-checkbox value="initiate-outbound" Initiate outbound transfers
  sl-checkbox value="approve-outbound" Approve outbound transfers
  sl-checkbox value="export" Export transactions
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';

const App = () => (
  <SlRadioGroup label="Select an option" name="a" value="1">
    <SlRadio value="1">Option 1</SlRadio>
    <SlRadio value="2">Option 2</SlRadio>
    <SlRadio value="3">Option 3</SlRadio>
  </SlRadioGroup>
);

Label with Tooltip

Use the label-tooltip attribute to add text that appears in a tooltip triggered by an info icon next to the label.

Initiate outbound transfers Approve outbound transfers Export transactions
<sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" label-tooltip="These apply to cash account only">
  <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox>
  <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox>
  <sl-checkbox value="export">Export transactions</sl-checkbox>
</sl-checkbox-group>
sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" label-tooltip="These apply to cash account only"
  sl-checkbox value="initiate-outbound" Initiate outbound transfers
  sl-checkbox value="approve-outbound" Approve outbound transfers
  sl-checkbox value="export" Export transactions
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';

const App = () => (
  <SlRadioGroup label="Select an option" name="a" value="1">
    <SlRadio value="1">Option 1</SlRadio>
    <SlRadio value="2">Option 2</SlRadio>
    <SlRadio value="3">Option 3</SlRadio>
  </SlRadioGroup>
);

Horizontal Checkbox Group

Use the horizontal attribute to lay out multiple checkbox items horizontally.

Manage transfers Export transactions
<sl-checkbox-group id="permissions" label="Financial products permissions" horizontal>
  <sl-checkbox value="manage-transfers">Manage transfers</sl-checkbox>
  <sl-checkbox value="export">Export transactions</sl-checkbox>
</sl-checkbox-group>

<style>
  sl-checkbox-group[id="permissions"] {
    container-type: inline-size;
    container-name: permissions;
  }

  @container permissions (max-width: 400px) {
    sl-checkbox-group[id="permissions"]::part(form-control-input) {
      flex-direction: column;
    }
  }
</style>
sl-checkbox-group id="permissions" label="Financial products permissions"
  sl-checkbox value="manage-transfers" Manage transfers
  sl-checkbox value="export" Export transactions

css:
  sl-checkbox-group[id="permissions"] {
    container-type: inline-size;
    container-name: permissions;
  }

  @container permissions (max-width: 400px) {
    sl-checkbox-group[id="permissions"]::part(form-control-input) {
      flex-direction: column;
    }
  }
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';

const App = () => (
  <SlRadioGroup label="Select an option" name="a" value="1">
    <SlRadio value="1">Option 1</SlRadio>
    <SlRadio value="2">Option 2</SlRadio>
    <SlRadio value="3">Option 3</SlRadio>
  </SlRadioGroup>
);

Contained Checkbox Group

Use the contained attribute to draw a card-like container around each checkbox item in the checkbox group. This style is useful for giving more emphasis to the list of options.

This option can be combined with the horizontal attribute.

Initiate outbound transfers Approve outbound transfers Export transactions

Initiate outbound transfers Approve outbound transfers
<sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained>
  <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox>
  <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox>
  <sl-checkbox value="export">Export transactions</sl-checkbox>
</sl-checkbox-group>
<br/>
<br/>
<sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained horizontal>
  <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox>
  <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox>
</sl-checkbox-group>
sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained="true"
  sl-checkbox value="initiate-outbound" Initiate outbound transfers
  sl-checkbox value="approve-outbound" Approve outbound transfers
  sl-checkbox value="export" Export transactions
br
br
sl-checkbox-group label="Financial products permissions" help-text="Outbound transfers require separate initiators and approvers" contained="true" horizontal="true"
  sl-checkbox value="initiate-outbound" Initiate outbound transfers
  sl-checkbox value="approve-outbound" Approve outbound transfers
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';

const App = () => (
  <SlRadioGroup label="Select an option" name="a" value="1">
    <SlRadio value="1">Option 1</SlRadio>
    <SlRadio value="2">Option 2</SlRadio>
    <SlRadio value="3">Option 3</SlRadio>
  </SlRadioGroup>
);

Disabling Options

Checkboxes can be disabled by adding the disabled attribute to the respective options inside the checkbox group.

Initiate outbound transfers Approve outbound transfers Export transactions
<sl-checkbox-group label="Financial products permissions" help-text="Exporting is currently disabled for all users" required>
  <sl-checkbox value="initiate-outbound">Initiate outbound transfers</sl-checkbox>
  <sl-checkbox value="approve-outbound">Approve outbound transfers </sl-checkbox>
  <sl-checkbox value="export" disabled>Export transactions</sl-checkbox>
</sl-checkbox-group>
sl-checkbox-group label="Financial products permissions"
  sl-checkbox value="initiate-outbound" Initiate outbound transfers
  sl-checkbox value="approve-outbound" Approve outbound transfers
  sl-checkbox value="export" Export transactions
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';

const App = () => (
  <SlRadioGroup label="Select an option" name="a" value="1">
    <SlRadio value="1">Option 1</SlRadio>
    <SlRadio value="2">Option 2</SlRadio>
    <SlRadio value="3">Option 3</SlRadio>
  </SlRadioGroup>
);

Validation

Set the required attribute to make selecting at least one option mandatory. If at least one value has not been selected, it will prevent the form from submitting and display an error message.

Option 1 Option 2 Option 3
Submit
<form class="validation">
  <sl-checkbox-group label="Select at least one option" required>
    <sl-checkbox value="option-1">Option 1</sl-checkbox>
    <sl-checkbox value="option-2">Option 2</sl-checkbox>
    <sl-checkbox value="option-3">Option 3</sl-checkbox>
  </sl-checkbox-group>
  <br />
  <sl-button type="submit" variant="primary">Submit</sl-button>
</form>

<script type="module">
  const form = document.querySelector('.validation');

  // Wait for controls to be defined before attaching form listeners
  await Promise.all([
    customElements.whenDefined('sl-checkbox-group'),
  ]).then(() => {
    form.addEventListener('submit', event => {
      event.preventDefault();
      alert('All fields are valid!');
    });
  });
</script>
form.validation
  sl-radio-group label="Select at least one option" required="true"
    sl-radio value="1" Option 1
    sl-radio value="2" Option 2
    sl-radio value="3" Option 3
  br
  sl-button type="submit" variant="primary" Submit

javascript:
  const form = document.querySelector(.validation);

  // Wait for controls to be defined before attaching form listeners
  await Promise.all([
    customElements.whenDefined('sl-checkbox-group'),
  ]).then(() => {
    // Handle form submit
    form.addEventListener(submit, event => {
      event.preventDefault();
      alert(All fields are valid!);
    });
  });
import SlButton from '@teamshares/shoelace/dist/react/button';
import SlIcon from '@teamshares/shoelace/dist/react/icon';
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';
const App = () => {
  function handleSubmit(event) {
    event.preventDefault();
    alert('All fields are valid!');
  }

  return (
    <form class="custom-validity" onSubmit={handleSubmit}>
      <SlRadioGroup label="Select an option" name="a" required onSlChange={handleChange}>
        <SlRadio value="1">
          Option 1
        </SlRadio>
        <SlRadiovalue="2">
          Option 2
        </SlRadio>
        <SlRadio value="3">
          Option 3
        </SlRadio>
      </SlRadioGroup>
      <br />
      <SlButton type="submit" variant="primary">
        Submit
      </SlButton>
    </form>
  );
};

Custom Validity

Use the setCustomValidity() method to set a custom validation message. This will prevent the form from submitting and make the browser display the error message you provide. To clear the error, call this function with an empty string.

You can optionally choose me I’m optional too You must choose me
Submit
<form class="custom-validity">
  <sl-checkbox-group label="Select the third option" required>
    <sl-checkbox value="option-1">You can optionally choose me</sl-checkbox>
    <sl-checkbox value="option-2">I'm optional too</sl-checkbox>
    <sl-checkbox value="option-3">You must choose me</sl-checkbox>
  </sl-checkbox-group>
  <br />
  <sl-button type="submit" variant="primary">Submit</sl-button>
</form>

<script type="module">
  const form = document.querySelector('.custom-validity');
  const checkboxGroup = form.querySelector('sl-checkbox-group');
  const errorMessage = 'You must choose the last option';

  // Set initial validity as soon as the element is defined
  customElements.whenDefined('sl-checkbox').then(() => {
    checkboxGroup.setCustomValidity(errorMessage);
  });

  // Update validity when a selection is made
  form.addEventListener('sl-change', () => {
    const isValid = checkboxGroup.value.some(value => value.includes('option-3: true'));
    checkboxGroup.setCustomValidity(isValid ? '' : errorMessage);
  });

  // Wait for controls to be defined before attaching form listeners
  await Promise.all([
    customElements.whenDefined('sl-checkbox-group'),
  ]).then(() => {
    form.addEventListener('submit', event => {
      event.preventDefault();
      alert('All fields are valid!');
    });
  });
</script>
form.validation
  sl-radio-group label="Select the third option" required="true"
    sl-radio value="1" You can optionally choose me
    sl-radio value="2" I'm optional too
    sl-radio value="3" You must choose me
  br
  sl-button type="submit" variant="primary" Submit

javascript:
  const form = document.querySelector(.custom-validity);
  const checkboxGroup = form.querySelector('sl-checkbox-group');
  const errorMessage = 'You must choose the last option';

  // Set initial validity as soon as the element is defined
  customElements.whenDefined('sl-checkbox').then(() => {
    checkboxGroup.setCustomValidity(errorMessage);
  });

  // Update validity when a selection is made
  form.addEventListener('sl-change', () => {
    const isValid = checkboxGroup.value.some(value => value.includes('option-3: true'));
    checkboxGroup.setCustomValidity(isValid ? '' : errorMessage);
  });

  // Wait for controls to be defined before attaching form listeners
  await Promise.all([
    customElements.whenDefined('sl-checkbox-group'),
  ]).then(() => {
    // Handle form submit
    form.addEventListener(submit, event => {
      event.preventDefault();
      alert(All fields are valid!);
    });
  });
import SlButton from '@teamshares/shoelace/dist/react/button';
import SlIcon from '@teamshares/shoelace/dist/react/icon';
import SlRadio from '@teamshares/shoelace/dist/react/radio';
import SlRadioGroup from '@teamshares/shoelace/dist/react/radio-group';
const App = () => {
  function handleSubmit(event) {
    event.preventDefault();
    alert('All fields are valid!');
  }

  return (
    <form class="custom-validity" onSubmit={handleSubmit}>
      <SlRadioGroup label="Select an option" name="a" required onSlChange={handleChange}>
        <SlRadio value="1">
          Option 1
        </SlRadio>
        <SlRadiovalue="2">
          Option 2
        </SlRadio>
        <SlRadio value="3">
          Option 3
        </SlRadio>
      </SlRadioGroup>
      <br />
      <SlButton type="submit" variant="primary">
        Submit
      </SlButton>
    </form>
  );
};

Usage Guidelines

When to Use a Checkbox Group

  • When you want people to choose one or more options from a list
  • When presenting fewer than 7 options
  • If letting people see all their options right away (without an additional click) is a priority

When to Use a Different Component

  • Use a radio group instead if presenting fewer than 5 to 7 options and you want to let people choose just one option
  • Use a multi-select select instead if presenting more than 7 options or there isn’t enough room to present all the options

Labels, Help Text, Etc.

Importing

If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.

Script Import Bundler React

To import this component from the CDN using a script tag:

<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.1.0/cdn/components/checkbox-group/checkbox-group.js"></script>

To import this component from the CDN using a JavaScript import:

import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.1.0/cdn/components/checkbox-group/checkbox-group.js';

To import this component using a bundler:

import '@shoelace-style/shoelace/dist/components/checkbox-group/checkbox-group.js';

To import this component as a React component:

import SlCheckboxGroup from '@shoelace-style/shoelace/dist/react/checkbox-group';

Slots

Name Description
(default) The default slot where <sl-checkbox> elements are placed.
label The checkbox group’s label. Required for proper accessibility. Alternatively, you can use the label attribute.
label-tooltip Used to add text that is displayed in a tooltip next to the label. Alternatively, you can use the label-tooltip attribute.
help-text Text that describes how to use the checkbox group. Alternatively, you can use the help-text attribute.

Learn more about using slots.

Properties

Name Description Reflects Type Default
label The checkbox group’s label. Required for proper accessibility. If you need to display HTML, use the label slot instead. string ''
labelTooltip
label-tooltip
Text that appears in a tooltip next to the label. If you need to display HTML in the tooltip, use the label-tooltip slot instead. string ''
helpText
help-text
The checkbox groups’s help text. If you need to display HTML, use the help-text slot instead. string ''
name The name of the checkbox group, submitted as a name/value pair with form data. string ''
value The current value of the checkbox group, submitted as a name/value pair with form data. string[] []
size The radio group’s size. This size will be applied to all child radios and radio buttons. 'small' | 'medium' | 'large' 'medium'
horizontal The radio group’s orientation. Changes the group’s layout from the default (vertical) to horizontal. boolean false
contained The radio group’s style. Changes the group’s style from the default (plain) style to the ‘contained’ style. This style will be applied to all child radios (but not child radio buttons, which do not have the ‘contained’ style as an option). boolean false
form By default, form controls are associated with the nearest containing <form> element. This attribute allows you to place the form control outside of a form and associate it with the form that has this id. The form must be in the same document or shadow root for this to work. string ''
required Ensures a child radio is checked before allowing the containing form to submit. boolean false
validity Gets the validity state object - -
validationMessage Gets the validation message - -
updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Events

Name React Event Description Event Detail
sl-change onSlChange Emitted when the checkbox group’s selected value changes. -
sl-input onSlInput Emitted when the checkbox group receives user input. -
sl-invalid onSlInvalid Emitted when the form control has been checked for validity and its constraints aren’t satisfied. -

Learn more about events.

Methods

Name Description Arguments
checkValidity() Checks for validity but does not show a validation message. Returns true when valid and false when invalid. -
getForm() Gets the associated form, if one exists. -
reportValidity() Checks for validity and shows the browser’s validation message if the control is invalid. -
setCustomValidity() Sets a custom validation message. Pass an empty string to restore validity. message:

Learn more about methods.

Parts

Name Description
form-control The form control that wraps the label, input, and help text.
form-control-label The label’s wrapper.
form-control-input The input’s wrapper.
form-control-help-text The help text’s wrapper.

Learn more about customizing CSS parts.