Skip to main content

Testing

Help us to improve the ONS Design System. Take part in a short study

Radios

Radios let the user select a single option from a list.

<div class="question u-mt-no">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">What type of accommodation do you live in?</h1>
    </legend>
    <div class="input-items">
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="house" class="radio__input js-radio" value="house" name="property-type">
            <label class="radio__label  " for="house" id="house-label">House or bungalow
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="flat" class="radio__input js-radio" value="flat" name="property-type">
            <label class="radio__label  " for="flat" id="flat-label">Flat, maisonette or apartment
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="mobile" class="radio__input js-radio" value="mobile" name="property-type">
            <label class="radio__label  " for="mobile" id="mobile-label">Caravan or other mobile or temporary structure
            </label>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/radios/_macro.njk" import onsRadios %}
{% from "components/question/_macro.njk" import onsQuestion %}
{% call onsQuestion({
    "title": "What type of accommodation do you live in?",
    "classes": "u-mt-no",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsRadios({
            "name": "property-type",
            "dontWrap": true,
            "radios": [
                {
                    "id": "house",
                    "label": {
                        "text": "House or bungalow"
                    },
                    "value": "house"
                },
                {
                    "id": "flat",
                    "label": {
                        "text": "Flat, maisonette or apartment"
                    },
                    "value": "flat"
                },
                {
                    "id": "mobile",
                    "label": {
                        "text": "Caravan or other mobile or temporary structure"
                    },
                    "value": "mobile"
                }
            ]
        })
    }}
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

When to use this component

Use the radio component when you need to help users select a single option from a list.

When not to use this component

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

How to use this component

Radios 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 radios in the list. The description is populated by providing a description parameter within the radio’s label parameter.

<div class="question u-mt-no">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">What is your ethnic group or background?</h1>
    </legend>
    <div class="input-items">
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="white" class="radio__input js-radio" value="" name="ethnicity">
            <label class="radio__label  label--with-description " for="white" id="white-label">White
              <span id="white-label-description-hint" class="label__description radio__label--with-description">
                Includes British, Northern Irish, Irish, Gypsy, Irish Traveller, Roma or any other White background
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="mixed" class="radio__input js-radio" value="" name="ethnicity">
            <label class="radio__label  label--with-description " for="mixed" id="mixed-label">Mixed or Multiple ethnic groups
              <span id="mixed-label-description-hint" class="label__description radio__label--with-description">
                Includes White and Black Caribbean, White and Black African, White and Asian or any other Mixed or Multiple background
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="asian" class="radio__input js-radio" value="" name="ethnicity">
            <label class="radio__label  label--with-description " for="asian" id="asian-label">Asian or Asian British
              <span id="asian-label-description-hint" class="label__description radio__label--with-description">
                Includes Indian, Pakistani, Bangladeshi, Chinese or any other Asian background
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="black" class="radio__input js-radio" value="" name="ethnicity">
            <label class="radio__label  label--with-description " for="black" id="black-label">Black, Black British, Caribbean or African
              <span id="black-label-description-hint" class="label__description radio__label--with-description">
                Includes Black British, Caribbean, African or any other Black background
              </span>
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="other" class="radio__input js-radio" value="" name="ethnicity">
            <label class="radio__label  label--with-description " for="other" id="other-label">Other ethnic group
              <span id="other-label-description-hint" class="label__description radio__label--with-description">
                Includes Arab or any other ethnic group
              </span>
            </label>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/radios/_macro.njk" import onsRadios %}
{% from "components/question/_macro.njk" import onsQuestion %}
{% call onsQuestion({
    "title": "What is your ethnic group or background?",
    "classes": "u-mt-no",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsRadios({
            "dontWrap": true,
            "name": "ethnicity",
            "radios": [
                {
                    "id": "white",
                    "label": {
                        "text": "White",
                        "description": "Includes British, Northern Irish, Irish, Gypsy, Irish Traveller, Roma or any other White background"
                    },
                    "name": "white"
                },
                {
                    "id": "mixed",
                    "label": {
                        "text": "Mixed or Multiple ethnic groups",
                        "description": "Includes White and Black Caribbean, White and Black African, White and Asian or any other Mixed or Multiple background"
                    },
                    "name": "mixed"
                },
                {
                    "id": "asian",
                    "label": {
                        "text": "Asian or Asian British",
                        "description": "Includes Indian, Pakistani, Bangladeshi, Chinese or any other Asian background"
                    },
                    "name": "asian"
                },
                {
                    "id": "black",
                    "label": {
                        "text": "Black, Black British, Caribbean or African",
                        "description": "Includes Black British, Caribbean, African or any other Black background"
                    },
                    "name": "black"
                },
                {
                    "id": "other",
                    "label": {
                        "text": "Other ethnic group",
                        "description": "Includes Arab or any other ethnic group"
                    },
                    "name": "other"
                }
            ]
        })
    }}
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

Radio with input

This variant lets the user provide an answer other to the radios 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 radio__other, added directly after the radio label. CSS hides this field until the radio is :checked.

<div class="question u-mt-no">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">How do you usually travel to work?</h1>
    </legend>
    <div class="input-items">
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="home" class="radio__input js-radio" value="home" name="travel">
            <label class="radio__label  " for="home" id="home-label">Work mainly from home
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="car" class="radio__input js-radio" value="car" name="travel">
            <label class="radio__label  " for="car" id="car-label">Car or van
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="underground" class="radio__input js-radio" value="underground" name="travel">
            <label class="radio__label  " for="underground" id="underground-label">Underground, metro, light rail or tram
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="train" class="radio__input js-radio" value="train" name="travel">
            <label class="radio__label  " for="train" id="train-label">Train
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="bus" class="radio__input js-radio" value="bus" name="travel">
            <label class="radio__label  " for="bus" id="bus-label">Bus, minibus or coach
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="bicycle" class="radio__input js-radio" value="bicycle" name="travel">
            <label class="radio__label  " for="bicycle" id="bicycle-label">Bicycle
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="walk" class="radio__input js-radio" value="walk" name="travel">
            <label class="radio__label  " for="walk" id="walk-label">Walk
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="other-radio" class="radio__input js-radio" value="other" name="travel" aria-controls="other-radio-other-wrap" aria-haspopup="true">
            <label class="radio__label  " for="other-radio" id="other-radio-label">Other
            </label>
            <span class="radio__other" id="other-radio-other-wrap">
              <label class="label u-fs-s--b " for="other-textbox" id="other-textbox-label">Enter how you travel
              </label>
              <input type="text" id="other-textbox" class="input input--text input-type__input input--w-auto " name="other-answer" />
            </span>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/radios/_macro.njk" import onsRadios %}
{% from "components/question/_macro.njk" import onsQuestion %}
{% call onsQuestion({
    "title": "How do you usually travel to work?",
    "classes": "u-mt-no",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsRadios({
            "dontWrap": true,
            "name": "travel",
            "radios": [
                {
                    "id": "home",
                    "label": {
                        "text": "Work mainly from home"
                    },
                    "value": "home"
                },
                {
                    "id": "car",
                    "label": {
                        "text": "Car or van"
                    },
                    "value": "car"
                },
                {
                    "id": "underground",
                    "label": {
                        "text": "Underground, metro, light rail or tram"
                    },
                    "value": "underground"
                },
                {
                    "id": "train",
                    "label": {
                        "text": "Train"
                    },
                    "value": "train"
                },
                {
                    "id": "bus",
                    "label": {
                        "text": "Bus, minibus or coach"
                    },
                    "value": "bus"
                },
                {
                    "id": "bicycle",
                    "label": {
                        "text": "Bicycle"
                    },
                    "value": "bicycle"
                },
                {
                    "id": "walk",
                    "label": {
                        "text": "Walk"
                    },
                    "value": "walk"
                },
                {
                    "id": "other-radio",
                    "label": {
                        "text": "Other"
                    },
                    "value": "other",
                    "other": {
                        "otherType": "input",
                        "id": "other-textbox",
                        "name": "other-answer",
                        "label": {
                            "text": "Enter how you travel"
                        }
                    }
                }
            ]
        })
    }}
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

Radio with visible input

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

<div class="question u-mt-no">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">Is the gender you identify with the same as your sex registered at birth?</h1>
    </legend>
    <div class="input-items">
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="yes" class="radio__input js-radio" value="yes" name="gender-identity">
            <label class="radio__label  " for="yes" id="yes-label">Yes
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="no" class="radio__input js-radio" value="no" name="gender-identity">
            <label class="radio__label  " for="no" id="no-label">No
            </label>
            <span class="radio__other radio__other--open" id="no-other-wrap">
              <label class="label u-fs-s--b " for="no-textbox" id="no-textbox-label">Enter your gender identity
              </label>
              <input type="text" id="no-textbox" class="input input--text input-type__input input--w-auto " name="no-answer" />
            </span>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/radios/_macro.njk" import onsRadios %}
{% from "components/question/_macro.njk" import onsQuestion %}
{% call onsQuestion({
    "title": "Is the gender you identify with the same as your sex registered at birth?",
    "classes": "u-mt-no",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsRadios({
            "dontWrap": true,
            "name": "gender-identity",
            "radios": [
                {
                    "id": "yes",
                    "label": {
                        "text": "Yes"
                    },
                    "value": "yes"
                },
                {
                    "id": "no",
                    "label": {
                        "text": "No"
                    },
                    "value": "no",
                    "other": {
                        "open": true,
                        "otherType": "input",
                        "id": "no-textbox",
                        "name": "no-answer",
                        "label": {
                            "text": "Enter your gender identity"
                        }
                    }
                }
            ]
        })
    }}
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

Radio with drop-down

This variant uses a select component instead of an input.

<div class="question">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">How would you like us to contact you?</h1>
    </legend>
    <div class="input-items">
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="post" class="radio__input js-radio" value="post" name="contact">
            <label class="radio__label  " for="post" id="post-label">By post
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="email" class="radio__input js-radio" value="email" name="contact">
            <label class="radio__label  " for="email" id="email-label">By email
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="phone" class="radio__input js-radio" value="phone" name="contact" aria-controls="phone-other-wrap" aria-haspopup="true">
            <label class="radio__label  " for="phone" id="phone-label">By phone
            </label>
            <span class="radio__other" id="phone-other-wrap">
              <label class="label u-fs-s--b " for="phone-time">Choose preferred time of day
              </label>
              <select id="phone-time" name="phone-time" class="input input--select">
                <option value="" selected disabled>Select an option</option>
                <option value="anytime">Any time 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>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/radios/_macro.njk" import onsRadios %}
{% call onsQuestion({
    "title": "How would you like us to contact you?",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsRadios({
            "dontWrap": true,
            "name": "contact",
            "radios": [
                {
                    "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": "Any time of day"
                            },
                            {
                                "value": "morning",
                                "text": "Morning"
                            },
                            {
                                "value": "afternoon",
                                "text": "Afternoon"
                            },
                            {
                                "value": "evening",
                                "text": "Evening"
                            }
                        ]
                    }
                }
            ]
        })
    }}
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

Radios with an “or” separator

<div class="question">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">How satisfied are you with this service?</h1>
    </legend>
    <div class="input-items">
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="very-satisfied" class="radio__input js-radio" value="very-satisfied" name="satisfaction">
            <label class="radio__label  " for="very-satisfied" id="very-satisfied-label">Very satisfied
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="somewhat-satisfied" class="radio__input js-radio" value="somewhat-satisfied" name="satisfaction">
            <label class="radio__label  " for="somewhat-satisfied" id="somewhat-satisfied-label">Somewhat satisfied
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="neither" class="radio__input js-radio" value="neither" name="satisfaction">
            <label class="radio__label  " for="neither" id="neither-label">Neither satisfied or dissatisfied
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="somewhat-dissatisfied" class="radio__input js-radio" value="somewhat-dissatisfied" name="satisfaction">
            <label class="radio__label  " for="somewhat-dissatisfied" id="somewhat-dissatisfied-label">Somewhat dissatisfied
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="very-dissatisfied" class="radio__input js-radio" value="very-dissatisfied" name="satisfaction">
            <label class="radio__label  " for="very-dissatisfied" id="very-dissatisfied-label">Very dissatisfied
            </label>
          </span>
        </p>
        <br>
        <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">Or </span>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="no" class="radio__input js-radio" value="no" name="satisfaction">
            <label class="radio__label  " for="no" id="no-label">I don’t want to give feedback
            </label>
          </span>
        </p>
      </div>
    </div>
  </fieldset>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/radios/_macro.njk" import onsRadios %}
{% call onsQuestion({
    "title": "How satisfied are you with this service?",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsRadios({
            "dontWrap": true,
            "name": "satisfaction",
            "or": "Or",
            "radios": [
                {
                    "id": "very-satisfied",
                    "label": {
                        "text": "Very satisfied"
                    },
                    "value": "very-satisfied"
                },
                {
                    "id": "somewhat-satisfied",
                    "label": {
                        "text": "Somewhat satisfied"
                    },
                    "value": "somewhat-satisfied"
                },
                {
                    "id": "neither",
                    "label": {
                        "text": "Neither satisfied or dissatisfied"
                    },
                    "value": "neither"
                },
                {
                    "id": "somewhat-dissatisfied",
                    "label": {
                        "text": "Somewhat dissatisfied"
                    },
                    "value": "somewhat-dissatisfied"
                },
                {
                    "id": "very-dissatisfied",
                    "label": {
                        "text": "Very dissatisfied"
                    },
                    "value": "very-dissatisfied"
                },
                {
                    "id": "no",
                    "label": {
                        "text": "I don’t want to give feedback"
                    },
                    "value": "no"
                }
            ]
        })
    }}
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

Radios with the option to clear

This variant displays a ”Clear selection” button which allows the user to deselect/clear the fieldset so all radios are not :checked. The button is displayed after a radio is selected. The aria-live attribute is used for announcing changes in assistive technologies.

If this variant is implemented on a question page that contains a primary submit button, a hidden duplicate submit button should be added to the top of the form to ensure the default enter key behaviour actions this button, and not the clear button. The submit button should use the hidden attribute and also the u-d-no utility class to set the button to display:none. This hides the button both visually and from screen readers.

<div class="question">
  <fieldset class="fieldset">
    <legend class="fieldset__legend">
      <h1 id="fieldset-legend-title" class="fieldset__legend-title ">What is your religion?</h1>
    </legend>
    <div class="panel panel--info panel--no-title u-mb-m">
      <span class="u-vh">Important information: </span>
      <div class="panel__body">
        <p>This question is <strong>voluntary</strong></p>
      </div>
    </div>
    <form onsubmit="return false;">
      <div class="input-items">
        <div class="radios__items">
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="none" class="radio__input js-radio" value="none" name="religion">
              <label class="radio__label  " for="none" id="none-label">No religion
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="christian" class="radio__input js-radio" value="christian" name="religion">
              <label class="radio__label  label--with-description " for="christian" id="christian-label">Christian
                <span id="christian-label-description-hint" class="label__description radio__label--with-description">
                  Including Church of England, Catholic, Protestant and all other Christian denominations
                </span>
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="buddhist" class="radio__input js-radio" value="buddhist" name="religion">
              <label class="radio__label  " for="buddhist" id="buddhist-label">Buddhist
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="hindu" class="radio__input js-radio" value="hindu" name="religion">
              <label class="radio__label  " for="hindu" id="hindu-label">Hindu
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="jewish" class="radio__input js-radio" value="jewish" name="religion">
              <label class="radio__label  " for="jewish" id="jewish-label">Jewish
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="muslim" class="radio__input js-radio" value="muslim" name="religion">
              <label class="radio__label  " for="muslim" id="muslim-label">Muslim
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="sikh" class="radio__input js-radio" value="sikh" name="religion">
              <label class="radio__label  " for="sikh" id="sikh-label">Sikh
              </label>
            </span>
          </p>
          <br>
          <p class="radios__item">
            <span class="radio">
              <input type="radio" id="other-radio" class="radio__input js-radio" value="other" name="religion" aria-controls="other-radio-other-wrap" aria-haspopup="true">
              <label class="radio__label  " for="other-radio" id="other-radio-label">Any other religion
              </label>
              <span class="radio__other" id="other-radio-other-wrap">
                <label class="label u-fs-s--b " for="other-textbox" id="other-textbox-label">Enter your religion
                </label>
                <input type="text" id="other-textbox" class="input input--text input-type__input input--w-auto " name="other-answer" />
              </span>
            </span>
          </p>
        </div>
        <button type="submit" class="btn btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled" name="clear-radios">
          <span class="btn__inner">Clear selection</span>
        </button>
        <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="You can clear your answer using the clear selection button after the radio inputs" data-cleared="You have cleared your answer"></span>
      </div>
    </form>
  </fieldset>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/radios/_macro.njk" import onsRadios %}
{% from "components/button/_macro.njk" import onsButton %}
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/panel/_macro.njk" import onsPanel %}
{% call onsQuestion({
    "title": "What is your religion?",
    "legendIsQuestionTitle": true
}) %}
    {{
        onsPanel({
            "body": '<p>This question is <strong>voluntary</strong></p>',
            "classes": 'u-mb-m'
        })
    }}
    <form onsubmit="return false;">
        {{
            onsRadios({
                "dontWrap": true,
                "name": "religion",
                "clearRadios": {
                    "text": "Clear selection",
                    "name": "clear-radios",
                    "ariaClearText": "You can clear your answer using the clear selection button after the radio inputs",
                    "ariaClearedText": "You have cleared your answer"
                },
                "radios": [
                    {
                        "id": "none",
                        "label": {
                            "text": "No religion"
                        },
                        "value": "none"
                    },
                    {
                        "id": "christian",
                        "label": {
                            "text": "Christian",
                            "description": "Including Church of England, Catholic, Protestant and all other Christian denominations"
                        },
                        "value": "christian"
                    },
                    {
                        "id": "buddhist",
                        "label": {
                            "text": "Buddhist"
                        },
                        "value": "buddhist"
                    },
                    {
                        "id": "hindu",
                        "label": {
                            "text": "Hindu"
                        },
                        "value": "hindu"
                    },
                    {
                        "id": "jewish",
                        "label": {
                            "text": "Jewish"
                        },
                        "value": "jewish"
                    },
                    {
                        "id": "muslim",
                        "label": {
                            "text": "Muslim"
                        },
                        "value": "muslim"
                    },
                    {
                        "id": "sikh",
                        "label": {
                            "text": "Sikh"
                        },
                        "value": "sikh"
                    },
                    {
                        "id": "other-radio",
                        "label": {
                            "text": "Any other religion"
                        },
                        "value": "other",
                        "other": {
                            "otherType": "input",
                            "id": "other-textbox",
                            "name": "other-answer",
                            "label": {
                                "text": "Enter your religion"
                            }
                        }
                    }
                ]
            })
        }}
    </form>
{% endcall %}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

How to check radios

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

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

Error messages

Use the correct errors pattern and show the error details above the radios.

<div class="panel panel--error panel--no-title u-mb-s" id="dietary-error">
  <span class="u-vh">Error: </span>
  <div class="panel__body">
    <p class="panel__error">
      <strong>Enter your gender identity</strong>
    </p>
    <fieldset class="fieldset">
      <legend class="fieldset__legend">
      </legend>
      <div class="radios__items">
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="yes" class="radio__input js-radio" value="yes" name="gender-identity">
            <label class="radio__label  " for="yes" id="yes-label">Yes
            </label>
          </span>
        </p>
        <br>
        <p class="radios__item">
          <span class="radio">
            <input type="radio" id="no" class="radio__input js-radio" value="no" name="gender-identity" checked>
            <label class="radio__label  " for="no" id="no-label">No
            </label>
            <span class="radio__other radio__other--open" id="no-other-wrap">
              <label class="label u-fs-s--b " for="no-textbox" id="no-textbox-label">Enter your gender identity
              </label>
              <input type="text" id="no-textbox" class="input input--text input-type__input input--w-auto " name="no-answer" />
            </span>
          </span>
        </p>
      </div>
    </fieldset>
  </div>
</div>
Nunjucks macro options
Name Type Required Description
id string false Id to apply to the fieldset
classes string false Classes to apply to the fieldset
legend string true 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 radios
radios Array<Radio> true An array of radios to render
dontWrap boolean false Prevents the radios from being wrapped in a fieldset component
legendIsQuestionTitle boolean false Creates a h1 inside the legend further information
value string false Can be used to set the checked radio. This can also be achieved by setting the checked parameter on the Radio item to true
error Error (ref) false Configuration for validation errors
or string false Text for the or label
clearRadios Object<ClearRadios> false An object containing values for the clear selection button
open boolean false Whether the ‘other’ input should be displayed

Radio

Name Type Required Description
id string true The id of the radio
name string true The name of the radio
value string true The value of the radio
checked boolean false Whether the radio should be checked
label Label (ref) true Settings for the radio 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 radio input element

ClearRadios

Name Type Required Description
text string true The text displayed for the button
name string false The name attribute value for the button
ariaClearText string true The text to be announced to screen readers when a radio has been selected
ariaClearedText string true The text to be announced to screen readers when the button has been clicked
{% from "components/radios/_macro.njk" import onsRadios %}
{{
    onsRadios({
        "name": "gender-identity",
        "radios": [
            {
                "id": "yes",
                "label": {
                    "text": "Yes"
                },
                "value": "yes"
            },
            {
                "id": "no",
                "label": {
                    "text": "No"
                },
                "value": "no",
                "checked": true,
                "other": {
                    "open": true,
                    "otherType": "input",
                    "id": "no-textbox",
                    "name": "no-answer",
                    "label": {
                        "text": "Enter your gender identity"
                    }
                }
            }
        ],
        "error": {
            "id": "dietary-error",
            "text": "Enter your gender identity",
            "dsExample": isPatternLib
        }
    })
}}

{% macro onsRadios(params) %}
    {% from "components/fieldset/_macro.njk" import onsFieldset %}
    {% from "components/button/_macro.njk" import onsButton %}
    {% from "components/label/_macro.njk" import onsLabel %}
    {% call onsFieldset({
        "id": params.id,
        "classes": params.classes,
        "legend": params.legend,
        "legendClasses": params.legendClasses,
        "description": params.description,
        "dontWrap": params.dontWrap,
        "legendIsQuestionTitle": params.legendIsQuestionTitle,
        "error": params.error
    }) %}
        <div class="radios__items">
            {% for radio in params.radios %}
                {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                    <span class="radios__label u-mt-s u-fs-r--b" aria-hidden="true">{{ params.or }} </span>
                {% endif %}
                <p class="radios__item">
                    <span class="radio">
                        <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="radio__input js-radio{{ " " + radio.classes if radio.classes else "" }}"
                            value="{{ radio.value }}"
                            name="{{ params.name }}"
                            {% if (radio.checked is defined and radio.checked) or (params.value is defined and params.value == radio.value) %} checked {% endif %}
                            {% if radio.other is defined and radio.other and not radio.other.open %} aria-controls="{{ radio.id }}-other-wrap" aria-haspopup="true"{% endif %}
                            {% if radio.attributes is defined and radio.attributes %}{% for attribute, value in (radio.attributes.items() if radio.attributes is mapping and radio.attributes.items else radio.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %} {% endfor %}{% endif %}
                        >
                        {{ onsLabel({
                            "id": radio.id + "-label",
                            "for": radio.id,
                            "inputType": "radio",
                            "text": radio.label.text,
                            "classes": "radio__label " + radio.label.classes | default(''),
                            "description": radio.label.description
                        }) }}
                        {% if radio.other is defined and radio.other %}
                            {% set otherType = radio.other.otherType | default('input') %}
                            <span class="radio__other{{ " " + 'radio__other--open' if radio.other.open else "" }}" id="{{ radio.id }}-other-wrap">
                            {% if otherType == "input" %}
                                {% from "components/input/_macro.njk" import onsInput %}
                                {{
                                    onsInput({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "type": radio.other.type,
                                        "required": radio.other.required,
                                        "classes": "input--w-auto " + radio.other.classes | default(''),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value
                                    })
                                }}
                            {% elif otherType == "select" %}
                                {% from "components/select/_macro.njk" import onsSelect %}
                                {{
                                    onsSelect({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "options": radio.other.options,
                                        "classes": radio.other.classes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'u-fs-s--b'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% endif %}
                            </span>
                        {% endif %}
                    </span>
                </p>
                {% if not loop.last %}
                    <br>
                {% endif %}
            {% endfor %}
        </div>
        {% if params.clearRadios is defined and params.clearRadios %}
            {{ onsButton({
                "text": params.clearRadios.text,
                "name": params.clearRadios.name,
                "type": "submit",
                "classes": "btn--secondary btn--small js-clear-btn u-mt-s u-db-no-js_enabled"
            }) }}
            <span class="js-clear-radio-alert u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
        {% endif %}
    {% endcall %}
{% endmacro %}

.radio {
  @extend .checkbox;
  &__input {
    @extend .checkbox__input;
    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;
    &:checked {
      background: $color-input;
    }
  }
  &__label {
    @extend .checkbox__label;
    &--with-description {
      @extend .checkbox__label--with-description;
    }
  }
  &__description {
    @extend .checkbox__description;
  }
  &__other {
    @extend .checkbox__other;
  }
  &__input:not(:checked) ~ &__other--open {
    display: block;
  }
}
.radios {
  &__items {
    @extend .checkboxes__items;
  }
  &__item {
    @extend .checkboxes__item;
  }
  &__label {
    @extend .checkboxes__label;
  }
}

If a radio has not been selected

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

If it is a question with yes or no answers and a radio has not been selected

Use “Select an answer”.

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

Use “Enter [whatever it is]”.
For example, “Enter your gender identity”.

If “radio 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 your preferred time of day for 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 ‘Radios’ component on GitHub