Skip to main content

Checkboxes

Checkboxes let the user select one or more options from a list.

<div class="ons-question ons-u-mt-no">
  <fieldset class="ons-fieldset">
    <legend class="ons-fieldset__legend">
      <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title ">What devices do you own?</h1>
    </legend>
    <div class="ons-input-items">
      <p class="ons-checkboxes__label">Select all that apply</p>
      <div class="ons-checkboxes__items">
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="mobile-phone" class="ons-checkbox__input ons-js-checkbox " value="mobile-phone">
            <label class="ons-checkbox__label  " for="mobile-phone" id="mobile-phone-label">Mobile phone
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="tablet" class="ons-checkbox__input ons-js-checkbox " value="tablet">
            <label class="ons-checkbox__label  " for="tablet" id="tablet-label">Tablet
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="laptop" class="ons-checkbox__input ons-js-checkbox " value="laptop">
            <label class="ons-checkbox__label  " for="laptop" id="laptop-label">Laptop
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="desktop" class="ons-checkbox__input ons-js-checkbox " value="desktop">
            <label class="ons-checkbox__label  " for="desktop" id="desktop-label">Desktop computer
            </label>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}

{% call onsQuestion({
    "title": "What devices do you own?",
    "legendIsQuestionTitle": true,
    "classes": "ons-u-mt-no"
}) %}
    {{
        onsCheckboxes({
            "checkboxesLabel": "Select all that apply",
            "dontWrap": true,
            "name": "devices",
            "checkboxes": [
                {
                    "id": "mobile-phone",
                    "label": {
                        "text": "Mobile phone"
                    },
                    "value": "mobile-phone"
                },
                {
                    "id": "tablet",
                    "label": {
                        "text": "Tablet"
                    },
                    "value": "tablet"
                },
                {
                    "id": "laptop",
                    "label": {
                        "text": "Laptop"
                    },
                    "value": "laptop"
                },
                {
                    "id": "desktop",
                    "label": {
                        "text": "Desktop computer"
                    },
                    "value": "desktop"
                }
            ]
        })
    }}
{% endcall %}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

When to use this component

Use the checkboxes component when you need to help users select multiple options from a list.

When not to use this component

Do not use the checkboxes component if users can only choose one option from a list. In this case, use the radios component.

How to use this component

Checkboxes are grouped within a fieldset which starts with a <legend> which lets the user know what they need to do.

Variants

Descriptions

This variant allows you to add more context to the checkbox answers. The description is added by providing a description parameter within the checkbox’s label parameter.

Answer descriptions are a good way to provide examples to help a user answer a question without disrupting their journey through the survey.

Answer descriptions should:

  • be short – try to have no more than 100 characters
  • be clearly written
  • be relevant to that answer only, not any of the other answers
  • start with a capital letter
  • not have a full stop on the end

<div class="ons-question ons-u-mt-no">
  <fieldset class="ons-fieldset">
    <legend class="ons-fieldset__legend">
      <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title ">What type of central heating does your accommodation have?</h1>
    </legend>
    <div class="ons-input-items">
      <p class="ons-checkboxes__label"></p>
      <div class="ons-checkboxes__items">
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="none" class="ons-checkbox__input ons-js-checkbox " value="" name="none">
            <label class="ons-checkbox__label  " for="none" id="none-label">No central heating
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="mains-gas" class="ons-checkbox__input ons-js-checkbox " value="" name="mains-gas">
            <label class="ons-checkbox__label  ons-label--with-description " for="mains-gas" id="mains-gas-label">Gas
              <span id="mains-gas-label-description-hint" class="ons-label__description ons-checkbox__label--with-description">
                Including tank or bottled gas
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="electric" class="ons-checkbox__input ons-js-checkbox " value="" name="electric">
            <label class="ons-checkbox__label  ons-label--with-description " for="electric" id="electric-label">Electric
              <span id="electric-label-description-hint" class="ons-label__description ons-checkbox__label--with-description">
                Including storage headers
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="oil" class="ons-checkbox__input ons-js-checkbox " value="" name="oil">
            <label class="ons-checkbox__label  " for="oil" id="oil-label">Oil
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="wood" class="ons-checkbox__input ons-js-checkbox " value="" name="wood">
            <label class="ons-checkbox__label  ons-label--with-description " for="wood" id="wood-label">Wood
              <span id="wood-label-description-hint" class="ons-label__description ons-checkbox__label--with-description">
                For example, logs, waste wood or pellets
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="solid-fuel" class="ons-checkbox__input ons-js-checkbox " value="" name="solid-fuel">
            <label class="ons-checkbox__label  ons-label--with-description " for="solid-fuel" id="solid-fuel-label">Solid fuel
              <span id="solid-fuel-label-description-hint" class="ons-label__description ons-checkbox__label--with-description">
                For example, coal
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="renewable" class="ons-checkbox__input ons-js-checkbox " value="" name="renewable">
            <label class="ons-checkbox__label  ons-label--with-description " for="renewable" id="renewable-label">Renewable energy
              <span id="renewable-label-description-hint" class="ons-label__description ons-checkbox__label--with-description">
                For example, solar thermal or heat pumps
              </span>
            </label>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}
{% from "components/question/_macro.njk" import onsQuestion %}

{% call onsQuestion({
    "title": "What type of central heating does your accommodation have?",
    "classes": "ons-u-mt-no",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsCheckboxes({
            "dontWrap": true,
            "name": "central-heating",
            "checkboxes": [
                {
                    "id": "none",
                    "label": {
                        "text": "No central heating"
                    },
                    "name": "none"
                },
                {
                    "id": "mains-gas",
                    "label": {
                        "text": "Gas",
                        "description": "Including tank or bottled gas"
                    },
                    "name": "mains-gas"
                },
                {
                    "id": "electric",
                    "label": {
                        "text": "Electric",
                        "description": "Including storage headers"
                    },
                    "name": "electric"
                },
                {
                    "id": "oil",
                    "label": {
                        "text": "Oil"
                    },
                    "name": "oil"
                },
                {
                    "id": "wood",
                    "label": {
                        "text": "Wood",
                        "description": "For example, logs, waste wood or pellets"
                    },
                    "name": "wood"
                },
                {
                    "id": "solid-fuel",
                    "label": {
                        "text": "Solid fuel",
                        "description": "For example, coal"
                    },
                    "name": "solid-fuel"
                },
                {
                    "id": "renewable",
                    "label": {
                        "text": "Renewable energy",
                        "description": "For example, solar thermal or heat pumps"
                    },
                    "name": "renewable"
                }
            ]
        })
    }}
{% endcall %}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

Checkbox with input

This variant lets the user provide an answer other to the options in the list, or to provide additional information required to describe their answer.

Use this variation by wrapping the text field in a div with class ons-checkbox__other, added directly after the checkbox label. CSS hides this field until the checkbox is :checked.

<div class="ons-question ons-u-mt-no">
  <fieldset class="ons-fieldset">
    <legend class="ons-fieldset__legend">
      <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title ">Do you have any dietary requirements?</h1>
    </legend>
    <div class="ons-input-items">
      <p class="ons-checkboxes__label">Select all that apply</p>
      <div class="ons-checkboxes__items">
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="gluten-free" class="ons-checkbox__input ons-js-checkbox " value="gluten-free">
            <label class="ons-checkbox__label  " for="gluten-free" id="gluten-free-label">Gluten free
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="lactose-intolerant" class="ons-checkbox__input ons-js-checkbox " value="lactose-intolerant">
            <label class="ons-checkbox__label  " for="lactose-intolerant" id="lactose-intolerant-label">Lactose intolerant
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="vegan" class="ons-checkbox__input ons-js-checkbox " value="vegan">
            <label class="ons-checkbox__label  " for="vegan" id="vegan-label">Vegan
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="vegetarian" class="ons-checkbox__input ons-js-checkbox " value="vegetarian">
            <label class="ons-checkbox__label  " for="vegetarian" id="vegetarian-label">Vegetarian
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="other-checkbox" class="ons-checkbox__input ons-js-checkbox " value="other" aria-controls="other-checkbox-other-wrap" aria-haspopup="true">
            <label class="ons-checkbox__label  " for="other-checkbox" id="other-checkbox-label">Other
            </label>
            <span class="ons-checkbox__other" id="other-checkbox-other-wrap">
              <label class="ons-label ons-u-fs-s--b " for="other-textbox" id="other-textbox-label">Enter dietary requirements
              </label>
              <input type="text" id="other-textbox" class="ons-input ons-input--text ons-input-type__input ons-input--w-auto" name="other-answer" />
            </span>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}

{% call onsQuestion({
    "title": "Do you have any dietary requirements?",
    "legendIsQuestionTitle": true,
    "classes": "ons-u-mt-no"
}) %}
    {{
        onsCheckboxes({
            "checkboxesLabel": "Select all that apply",
            "dontWrap": true,
            "name": "dietary",
            "checkboxes": [
                {
                    "id": "gluten-free",
                    "label": {
                        "text": "Gluten free"
                    },
                    "value": "gluten-free"
                },
                {
                    "id": "lactose-intolerant",
                    "label": {
                        "text": "Lactose intolerant"
                    },
                    "value": "lactose-intolerant"
                },
                {
                    "id": "vegan",
                    "label": {
                        "text": "Vegan"
                    },
                    "value": "vegan"
                },
                {
                    "id": "vegetarian",
                    "label": {
                        "text": "Vegetarian"
                    },
                    "value": "vegetarian"
                },
                {
                    "id": "other-checkbox",
                    "label": {
                        "text": "Other"
                    },
                    "value": "other",
                    "other": {
                        "id": "other-textbox",
                        "name": "other-answer",
                        "label": {
                            "text": "Enter dietary requirements"
                        }
                    }
                }
            ]
        })
    }}
{% endcall %}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

Checkbox with visible input

This variant of “checkbox with input” shows the input instead of waiting for the checkbox to be :checked.

<div class="ons-question ons-u-mt-no">
  <fieldset class="ons-fieldset">
    <legend class="ons-fieldset__legend">
      <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title ">Do you have any dietary requirements?</h1>
    </legend>
    <div class="ons-input-items">
      <p class="ons-checkboxes__label">Select all that apply</p>
      <div class="ons-checkboxes__items">
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="gluten-free" class="ons-checkbox__input ons-js-checkbox " value="gluten-free">
            <label class="ons-checkbox__label  " for="gluten-free" id="gluten-free-label">Gluten free
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="lactose-intolerant" class="ons-checkbox__input ons-js-checkbox " value="lactose-intolerant">
            <label class="ons-checkbox__label  " for="lactose-intolerant" id="lactose-intolerant-label">Lactose intolerant
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="vegan" class="ons-checkbox__input ons-js-checkbox " value="vegan">
            <label class="ons-checkbox__label  " for="vegan" id="vegan-label">Vegan
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="vegetarian" class="ons-checkbox__input ons-js-checkbox " value="vegetarian">
            <label class="ons-checkbox__label  " for="vegetarian" id="vegetarian-label">Vegetarian
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="other-checkbox" class="ons-checkbox__input ons-js-checkbox " value="other">
            <label class="ons-checkbox__label  " for="other-checkbox" id="other-checkbox-label">Other
            </label>
            <span class="ons-checkbox__other ons-checkbox__other--open" id="other-checkbox-other-wrap">
              <label class="ons-label ons-u-fs-s--b " for="other-textbox" id="other-textbox-label">Enter dietary requirements
              </label>
              <input type="text" id="other-textbox" class="ons-input ons-input--text ons-input-type__input ons-input--w-auto" name="other-answer" />
            </span>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}

{% call onsQuestion({
    "title": "Do you have any dietary requirements?",
    "legendIsQuestionTitle": true,
    "classes": "ons-u-mt-no"
}) %}
    {{
        onsCheckboxes({
            "checkboxesLabel": "Select all that apply",
            "dontWrap": true,
            "name": "dietary",
            "checkboxes": [
                {
                    "id": "gluten-free",
                    "label": {
                        "text": "Gluten free"
                    },
                    "value": "gluten-free"
                },
                {
                    "id": "lactose-intolerant",
                    "label": {
                        "text": "Lactose intolerant"
                    },
                    "value": "lactose-intolerant"
                },
                {
                    "id": "vegan",
                    "label": {
                        "text": "Vegan"
                    },
                    "value": "vegan"
                },
                {
                    "id": "vegetarian",
                    "label": {
                        "text": "Vegetarian"
                    },
                    "value": "vegetarian"
                },
                {
                    "id": "other-checkbox",
                    "label": {
                        "text": "Other"
                    },
                    "value": "other",
                    "other": {
                        "open": true,
                        "id": "other-textbox",
                        "name": "other-answer",
                        "label": {
                            "text": "Enter dietary requirements"
                        }
                    }
                }
            ]
        })
    }}
{% endcall %}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

Checkbox with drop-down

This variant uses a select component instead of an input.

<div class="ons-question ons-u-mt-no">
  <fieldset class="ons-fieldset">
    <legend class="ons-fieldset__legend">
      <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title ">How would you like us to contact you?</h1>
    </legend>
    <div class="ons-input-items">
      <p class="ons-checkboxes__label">Select all that apply</p>
      <div class="ons-checkboxes__items">
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="post" class="ons-checkbox__input ons-js-checkbox " value="post">
            <label class="ons-checkbox__label  " for="post" id="post-label">By post
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="email" class="ons-checkbox__input ons-js-checkbox " value="email">
            <label class="ons-checkbox__label  " for="email" id="email-label">By email
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="phone" class="ons-checkbox__input ons-js-checkbox " value="phone" aria-controls="phone-other-wrap" aria-haspopup="true">
            <label class="ons-checkbox__label  " for="phone" id="phone-label">By phone
            </label>
            <span class="ons-checkbox__other" id="phone-other-wrap">
              <label class="ons-label ons-u-fs-s--b " for="phone-time">Choose preferred time of day
              </label>
              <select id="phone-time" name="phone-time" class="ons-input ons-input--select">
                <option value="" selected disabled>Select an option</option>
                <option value="anytime">Anytime of day</option>
                <option value="morning">Morning</option>
                <option value="afternoon">Afternoon</option>
                <option value="evening">Evening</option>
              </select>
            </span>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}

{% call onsQuestion({
    "title": "How would you like us to contact you?",
    "legendIsQuestionTitle": true,
    "classes": "ons-u-mt-no"
}) %}
    {{
        onsCheckboxes({
            "checkboxesLabel": "Select all that apply",
            "dontWrap": true,
            "name": "contact",
            "checkboxes": [
                {
                    "id": "post",
                    "label": {
                        "text": "By post"
                    },
                    "value": "post"
                },
                {
                    "id": "email",
                    "label": {
                        "text": "By email"
                    },
                    "value": "email"
                },
                {
                    "id": "phone",
                    "label": {
                        "text": "By phone"
                    },
                    "value": "phone",
                    "other": {
                        "otherType": "select",
                        "id": "phone-time",
                        "name": "phone-time",
                        "label": {
                            "text": "Choose preferred time of day"
                        },
                        "options": [
                            {
                                "value": "",
                                "text": "Select an option",
                                "disabled": true,
                                "selected": true
                            },
                            {
                                "value": "anytime",
                                "text": "Anytime of day"
                            },
                            {
                                "value": "morning",
                                "text": "Morning"
                            },
                            {
                                "value": "afternoon",
                                "text": "Afternoon"
                            },
                            {
                                "value": "evening",
                                "text": "Evening"
                            }
                        ]
                    }
                }
            ]
        })
    }}
{% endcall %}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

Checkbox without a border

This variant removes the border around the checkbox input and label. Do not use it for question pages with checkboxes. It is better to have a border. It makes the checkboxes more visible for users and gives them a larger target area to select (the label and the boundary).

Only remove the checkbox border for pages that are not following the practice of “one thing per page”, where the checkboxes are not the primary call to action. For example, the checkboxes could be one part of a multipurpose page, like the checkboxes used for the filters on the download resources pattern.

<fieldset class="ons-fieldset">
  <legend class="ons-fieldset__legend">
    Select type
  </legend>
  <div class="ons-input-items">
    <p class="ons-checkboxes__label ons-u-fs-s ons-u-mb-xs">All types</p>
    <div class="ons-checkboxes__items">
      <p class="ons-checkboxes__item ons-checkboxes__item--no-border">
        <span class="ons-checkbox ons-checkbox--no-border">
          <input type="checkbox" id="booklet" class="ons-checkbox__input ons-js-checkbox " value="booklet">
          <label class="ons-checkbox__label  " for="booklet" id="booklet-label">Booklet
          </label>
        </span>
      </p>
      <br>
      <p class="ons-checkboxes__item ons-checkboxes__item--no-border">
        <span class="ons-checkbox ons-checkbox--no-border">
          <input type="checkbox" id="logo" class="ons-checkbox__input ons-js-checkbox " value="logo">
          <label class="ons-checkbox__label  " for="logo" id="logo-label">Logo
          </label>
        </span>
      </p>
      <br>
      <p class="ons-checkboxes__item ons-checkboxes__item--no-border">
        <span class="ons-checkbox ons-checkbox--no-border">
          <input type="checkbox" id="poster" class="ons-checkbox__input ons-js-checkbox " value="poster">
          <label class="ons-checkbox__label  " for="poster" id="poster-label">Poster
          </label>
        </span>
      </p>
    </div>
  </div>
</fieldset>
{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}
{% from "components/fieldset/_macro.njk" import onsFieldset %}

{% call onsFieldset({
    "legend": "Select type"
}) %}
    {{
        onsCheckboxes({
            "checkboxesLabel": "All types",
            "checkboxesLabelClasses": "ons-u-fs-s ons-u-mb-xs",
            "dontWrap": true,
            "name": "types",
            "borderless": true,
            "checkboxes": [
                {
                    "id": "booklet",
                    "label": {
                        "text": "Booklet"
                    },
                    "value": "booklet"
                },
                {
                    "id": "logo",
                    "label": {
                        "text": "Logo"
                    },
                    "value": "logo"
                },
                {
                    "id": "poster",
                    "label": {
                        "text": "Poster"
                    },
                    "value": "poster"
                }
            ]
        })
    }}
{% endcall %}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

How to validate checkboxes

To help users make a selection on the page and provide extra detail if it is required, you should:

  • check they have selected at least one checkbox
  • check they have entered something or selected a drop-down option if more detail is required for one of the checkboxes
  • show an error message if they have not selected any of the checkboxes or given any more detail when required

Error messages

Use the correct errors pattern and show the error details above the checkbox options.

<div class="ons-panel ons-panel--error ons-panel--no-title ons-u-mb-s" id="dietary-error">
  <span class="ons-u-vh">Error: </span>
  <div class="ons-panel__body">
    <p class="ons-panel__error">
      <strong>Enter your dietary requirements</strong>
    </p>
    <div class="ons-input-items">
      <p class="ons-checkboxes__label">Select all that apply</p>
      <div class="ons-checkboxes__items">
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="gluten-free" class="ons-checkbox__input ons-js-checkbox " value="gluten-free">
            <label class="ons-checkbox__label  " for="gluten-free" id="gluten-free-label">Gluten free
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="lactose-intolerant" class="ons-checkbox__input ons-js-checkbox " value="lactose-intolerant">
            <label class="ons-checkbox__label  " for="lactose-intolerant" id="lactose-intolerant-label">Lactose intolerant
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="vegan" class="ons-checkbox__input ons-js-checkbox " value="vegan">
            <label class="ons-checkbox__label  " for="vegan" id="vegan-label">Vegan
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="vegetarian" class="ons-checkbox__input ons-js-checkbox " value="vegetarian">
            <label class="ons-checkbox__label  " for="vegetarian" id="vegetarian-label">Vegetarian
            </label>
          </span>
        </p>
        <br>
        <p class="ons-checkboxes__item">
          <span class="ons-checkbox ">
            <input type="checkbox" id="other-checkbox" class="ons-checkbox__input ons-js-checkbox " value="other" checked aria-controls="other-checkbox-other-wrap" aria-haspopup="true">
            <label class="ons-checkbox__label  " for="other-checkbox" id="other-checkbox-label">Other
            </label>
            <span class="ons-checkbox__other" id="other-checkbox-other-wrap">
              <label class="ons-label ons-u-fs-s--b " for="other-textbox" id="other-textbox-label">Enter dietary requirements
              </label>
              <input type="text" id="other-textbox" class="ons-input ons-input--text ons-input-type__input ons-input--w-auto" name="other-answer" />
            </span>
          </span>
        </p>
      </div>
    </div>
  </div>
</div>

{% from "components/checkboxes/_macro.njk" import onsCheckboxes %}

{{
    onsCheckboxes({
        "checkboxesLabel": "Select all that apply",
        "name": "dietary",
        "dontWrap": true,
        "checkboxes": [
            {
                "id": "gluten-free",
                "label": {
                    "text": "Gluten free"
                },
                "value": "gluten-free"
            },
            {
                "id": "lactose-intolerant",
                "label": {
                    "text": "Lactose intolerant"
                },
                "value": "lactose-intolerant"
            },
            {
                "id": "vegan",
                "label": {
                    "text": "Vegan"
                },
                "value": "vegan"
            },
            {
                "id": "vegetarian",
                "label": {
                    "text": "Vegetarian"
                },
                "value": "vegetarian"
            },
            {
                "id": "other-checkbox",
                "label": {
                    "text": "Other"
                },
                "checked": true,
                "value": "other",
                "other": {
                    "id": "other-textbox",
                    "name": "other-answer",
                    "label": {
                        "text": "Enter dietary requirements"
                    }
                }
            }
        ],
        "error": {
            "classes": "test",
            "id": "dietary-error",
            "text": "Enter your dietary requirements",
            "dsExample": isPatternLib
        }
    })
}}
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string false The legend to apply to the fieldset
legendClasses string false Classes to apply to the legend
name string true The name to apply to the checkboxes
checkboxesLabel string true Label to apply to the checkboxes
checkboxesLabelClasses string false Additional classes to apply to the checkboxesLabel
checkboxes Array<Checkbox> true An array of checkboxes to render
borderless boolean false Removes the border surrounding the input and label
mutuallyExclusive MutuallyExclusive (ref) false Configuration object if this is a mutually exclusive checkbox list
dontWrap boolean false Prevents the checkboxes from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend (further information)
open boolean false Whether the ‘other’ input should be displayed

Checkbox

Name Type Required Description
id string true The id of the checkbox
name string true The name of the checkbox
value string true The value of the checkbox
classes string false Classes to apply to the checkbox
inputClasses string false Classes to apply to the checkbox input
checked boolean false Whether the checkbox should be checked
label Label (ref) true Settings for the checkbox label
other Input (ref) or Select (ref) false Object with settings for other input or select
otherType string false (true if other provided) Can be set to select or input to set what other input you want in a radio
attributes object false HTML attributes (for example, data attributes) to add to the checkbox input element
error Error (ref) false Configuration for validation errors
deselectMessage string false For use with mutually exclusive checkboxes. The text the aria-live will read to warn that selecting the exclusive option will clear all other inputs errors
{% macro onsCheckboxes(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
    {% from "components/checkboxes/_checkbox-macro.njk" import onsCheckbox %}

    {% set fields %}
        <p class="ons-checkboxes__label{{ " " + params.checkboxesLabelClasses if params.checkboxesLabelClasses }}">{{ params.checkboxesLabel }}</p>
        <div class="ons-checkboxes__items">
            {% for checkbox in params.checkboxes %}
                {% set labelHTML = checkbox.label.text %}
                {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
                    {% set exclusiveClass = ' ons-js-exclusive-group-item' %}
                {% endif %}
                {% if params.borderless is defined and params.borderless %}
                    {% set borderless = "ons-checkbox--no-border" %}
                {% endif %}
                <p class="ons-checkboxes__item{{ " ons-checkboxes__item--no-border" if params.borderless }}">
                    {% set config = {
                        "id": checkbox.id,
                        "name": checkbox.name,
                        "value": checkbox.value,
                        "checked": checkbox.checked,
                        "classes": checkbox.classes | default('') + borderless | default(''),
                        "inputClasses": exclusiveClass,
                        "label": {
                            "for": checkbox.id,
                            "text": labelHTML,
                            "description": checkbox.label.description,
                            "classes": checkbox.label.classes | default('')
                        },
                        "attributes": checkbox.attributes
                    } %}

                    {% if checkbox.other is defined and checkbox.other %}
                        {% set config = config | setAttributes({
                            "other": {
                                "open": checkbox.other.open | default(false),
                                "id": checkbox.other.id,
                                "name": checkbox.other.name,
                                "type": checkbox.other.type,
                                "otherType": checkbox.other.otherType,
                                "options": checkbox.other.options,
                                "width": checkbox.other.width,
                                "classes": checkbox.other.classes | default('') + exclusiveClass | default(''),
                                "attributes": checkbox.other.attributes,
                                "label": {
                                    "text": checkbox.other.label.text
                                },
                                "value": checkbox.other.value
                            }
                        }) %}
                    {% endif %}
                    {{ onsCheckbox(config) }}
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
    {% endset %}

    {% if params.mutuallyExclusive is defined and params.mutuallyExclusive %}
        {% call onsMutuallyExclusive({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "checkbox": params.mutuallyExclusive.checkbox,
            "or": params.mutuallyExclusive.or,
            "deselectMessage": params.mutuallyExclusive.deselectMessage,
            "deselectGroupAdjective": params.mutuallyExclusive.deselectGroupAdjective,
            "deselectCheckboxAdjective": params.mutuallyExclusive.deselectCheckboxAdjective,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% else %}
        {% call onsFieldset({
            "id": params.id,
            "description": params.description,
            "classes": params.classes,
            "legend": params.legend,
            "legendClasses": params.legendClasses,
            "legendIsQuestionTitle": params.legendIsQuestionTitle,
            "description": params.description,
            "attributes": params.attributes,
            "dontWrap": params.dontWrap,
            "error": params.error
        }) %}
            {{ fields | safe }}
        {% endcall %}
    {% endif %}
{% endmacro %}
$checkbox-input-width: 22px;
$checkbox-padding: 11px;

.ons-checkbox {
  display: inline-block;
  position: relative;
  width: 100%;
  z-index: 1;

  &__input {
    appearance: none;
    background: url(#{$static}/img/icons--check.svg) no-repeat center center;
    background-color: $color-white;
    background-size: 0;
    border: 2px solid $color-input;
    border-radius: 0.2rem;
    box-sizing: border-box;
    height: $checkbox-input-width;
    left: $checkbox-padding;
    position: absolute;
    top: $checkbox-padding + 3px;
    width: $checkbox-input-width;
    z-index: 1;

    &:focus,
    &:checked {
      outline: none;
    }

    &:checked {
      background-size: 14px;
    }
  }

  &--no-border {
    & > .ons-checkbox__label {
      padding: 0 0 0 1.85rem;

      &::before {
        background: none;
        border: none;
        box-shadow: none;
      }

      & > .ons-checkbox__label--with-description {
        padding: 0;
      }
    }

    & > .ons-checkbox__input {
      left: 0.05rem;
      top: 0.15rem;

      &:checked,
      &:focus {
        background-color: initial;

        & + .ons-checkbox__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }
  }

  &__label {
    cursor: pointer;
    display: block;
    padding: $checkbox-padding 1rem $checkbox-padding ($checkbox-padding * 2 + $checkbox-input-width);
    width: 100%;

    &--with-description {
      padding: 0 1rem $checkbox-padding 0;
    }

    .ons-label__description {
      margin-left: -1.75rem;
    }

    &::before {
      background: $color-white;
      border: 1px solid $color-input;
      border-radius: 3px;
      bottom: 0;
      content: '';
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      z-index: -1;
    }

    * {
      pointer-events: none;
    }
  }

  &__description {
    display: block;
    margin-top: 0.25rem;
  }

  &__other {
    display: block;
    padding: 0 $checkbox-padding $checkbox-padding;
  }

  &__input:checked + &__label::before {
    background: $color-grey-5;
    box-shadow: 0 0 0 1px $color-input;
  }

  .ons-panel--error .ons-radio__input:checked ~ &__other > .ons-input--text:required:not(:focus) {
    border: 1px solid $color-ruby-red;
    outline: 1px solid $color-ruby-red;
    outline-offset: -2px;
  }

  &__input:focus + &__label::before {
    @extend .ons-input:focus;
  }

  &__input:not(:checked) ~ &__other {
    display: none;
  }

  &__input:not(:checked) ~ &__other--open {
    display: block;
  }

  &--toggle & {
    &__input {
      left: 0;
      top: 0.1rem;

      &:focus {
        box-shadow: 0 0 0 3px $color-focus;
      }
    }

    &__label {
      padding: 0 0 0 ($checkbox-input-width + $checkbox-padding);

      &::before {
        background: none;
        border: 0;
      }
    }

    &__input:checked + .ons-checkbox__label::before,
    &__input:focus + .ons-checkbox__label::before {
      background: transparent;
      box-shadow: none;
    }

    &__input:focus + .ons-checkbox__label::before {
      border: 0;
      outline: none;
    }
  }
}

.ons-checkboxes {
  &__label {
    display: block;
    margin: 0 0 0.5rem;
  }

  &__items {
    display: block;
  }

  &__item {
    display: inline-block;
    margin: 0 0 0.5rem;
    width: 100%;

    &:last-child {
      margin-bottom: 0;
    }

    @include mq(s) {
      min-width: 20rem;
      width: auto;

      &--no-border {
        min-width: 0;
      }
    }
  }

  &--mutually-exclusive__item {
    @extend .ons-checkboxes__item;

    margin-bottom: 0;
  }
}

If no checkbox options have been selected

Use “Select [whatever it is]”.
For example, “Select your dietary requirements”.

If “checkbox with input” is selected but the input field is empty

Use “Enter your [whatever it is]”.
For example, “Enter your sexual orientation”.

If “checkbox with drop-down” is selected but a drop-down option has not been selected

Use “Select [whatever topic the drop-down is asking for]”.
For example, “Select the time of day you would like us to contact you”.

Help improve this component

Let us know how we could improve this component or share your user research findings. Discuss the ‘Checkboxes’ component on GitHub