Skip to main content

Label

When to use this component

Labels are paired with inputs, textareas, radios, checkboxes, and selects to describe a form input.

<label class="label  " for="some-input" id="label">Label
</label>
Nunjucks macro options
Name Type Required Description
text string true The text content of the label
for string true The id of the input this label is for
description string false A secondary piece of information to help describe the input
id string false The id for the label
classes string false classes to add to the label
attributes object false HTML attributes to add to the label, e.g. data attributes
inputType string false If set to ‘radio’ or ‘checkbox’ will add the relevant css for checkboxes or radios, defaults to text input
{% from "components/label/_macro.njk" import onsLabel %}
{{
    onsLabel({
        "id": 'label',
        "for": "some-input",
        "text": 'Label'
    })
}}

{% macro onsLabel(params) %}
    {% set field %}
        <span
          {% if params.id is defined and params.id %} id="{{ params.id }}-description-hint"{% else %}id="description-hint"{% endif %}
          class="label__description {% if params.inputType is defined and params.inputType %}{{ params.inputType }}__label--with-description{% else %} input--with-description{% endif %}">
              {{ params.description }}
        </span>
    {% endset %}
    <label
        class="{% if params.inputType is not defined %}label {% endif %}{{ params.classes if params.classes else "" }}{% if params.description is defined and params.description %} label--with-description{% endif %} {{' label--placeholder ' if params.accessiblePlaceholder else "" }}"
        {% if params.for is defined and params.for %} for="{{ params.for }}"{% endif %}
        {% if params.id is defined and params.id %} id="{{ params.id }}"{% endif %}
        {% if params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %}{% endfor %}{% endif %}
    >
        {{- params.text | safe -}}
        {% if params.inputType is defined and params.inputType %}
            {% if params.inputType == "checkbox" or params.inputType == "radio" %}
                {%- if params.description is defined and params.description %}
                    {{ field | safe }}
                {% endif -%}
            {% endif %}
            </label>
        {% else %}
            </label>
            {%- if params.description is defined and params.description %}
                {{ field | safe }}
            {% endif -%}
        {% endif %}
{% endmacro %}

.label {
  color: inherit;
  display: block;
  font-weight: $font-weight-bold;
  margin-bottom: 0.4rem;
  &__description {
    @extend .u-fs-s;
    display: block;
    line-height: 1.4;
  }
  &--with-description {
    margin-bottom: 0;
    padding-bottom: 0;
  }
  &--placeholder {
    font-size: 1rem;
    font-weight: $font-weight-regular;
    left: 8px;
    position: absolute;
    top: 6px;
  }
}

How to use this component

Generally speaking you should not need to implement a label yourself as the form inputs have them imported in their respective templates.

All input and textarea components must have a visible label.

Do:

  • make sure the label is short, direct and written in sentence case
  • left-align the label above the input

Do not:

  • use placeholder text to display a label because it will not be visible when the user clicks on the input
  • place a colon at the end of the label

Variants

With description

Use the optional label__description to show hint text to help the majority of users, like how to enter their information, where to find it, or how it will be used.

<label class="label  label--with-description " for="some-input">Label
</label>
<span id="description-hint" class="label__description  input--with-description">
  An example description
</span>
Nunjucks macro options
Name Type Required Description
text string true The text content of the label
for string true The id of the input this label is for
description string false A secondary piece of information to help describe the input
id string false The id for the label
classes string false classes to add to the label
attributes object false HTML attributes to add to the label, e.g. data attributes
inputType string false If set to ‘radio’ or ‘checkbox’ will add the relevant css for checkboxes or radios, defaults to text input
{% from "components/label/_macro.njk" import onsLabel %}
{{
    onsLabel({
        "text": "Label",
        "for": "some-input",
        "description": "An example description"
    })
}}

{% macro onsLabel(params) %}
    {% set field %}
        <span
          {% if params.id is defined and params.id %} id="{{ params.id }}-description-hint"{% else %}id="description-hint"{% endif %}
          class="label__description {% if params.inputType is defined and params.inputType %}{{ params.inputType }}__label--with-description{% else %} input--with-description{% endif %}">
              {{ params.description }}
        </span>
    {% endset %}
    <label
        class="{% if params.inputType is not defined %}label {% endif %}{{ params.classes if params.classes else "" }}{% if params.description is defined and params.description %} label--with-description{% endif %} {{' label--placeholder ' if params.accessiblePlaceholder else "" }}"
        {% if params.for is defined and params.for %} for="{{ params.for }}"{% endif %}
        {% if params.id is defined and params.id %} id="{{ params.id }}"{% endif %}
        {% if params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %}{{ attribute }}{% if value is defined and value %}="{{ value }}"{% endif %}{% endfor %}{% endif %}
    >
        {{- params.text | safe -}}
        {% if params.inputType is defined and params.inputType %}
            {% if params.inputType == "checkbox" or params.inputType == "radio" %}
                {%- if params.description is defined and params.description %}
                    {{ field | safe }}
                {% endif -%}
            {% endif %}
            </label>
        {% else %}
            </label>
            {%- if params.description is defined and params.description %}
                {{ field | safe }}
            {% endif -%}
        {% endif %}
{% endmacro %}

.label {
  color: inherit;
  display: block;
  font-weight: $font-weight-bold;
  margin-bottom: 0.4rem;
  &__description {
    @extend .u-fs-s;
    display: block;
    line-height: 1.4;
  }
  &--with-description {
    margin-bottom: 0;
    padding-bottom: 0;
  }
  &--placeholder {
    font-size: 1rem;
    font-weight: $font-weight-regular;
    left: 8px;
    position: absolute;
    top: 6px;
  }
}

To label checkboxes or radios

Labels and descriptions are also used to label radios and checkboxes. To use it for radios or checkboxes inputType needs to be set to radio or checkbox which will style the component correctly, otherwise it will default to be styled as above for a text input.

<fieldset class="fieldset">
  <legend class="fieldset__legend">
    What is your ethnic group or background?
  </legend>
  <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, Caribbean, African or Black British
          <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>
</fieldset>
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
legendIsPageTitle 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({
        "legend": "What is your ethnic group or background?",
        "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, Caribbean, African or Black British",
                    "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"
            }
        ]
    })
}}

{% 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,
        "legendIsPageTitle": params.legendIsPageTitle,
        "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": params.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
                                    })
                                }}
                            {% 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;
  }
}

Help improve this component

Let us know how we could improve this component or share your user research findings.

Discuss the ‘Label’ component on GitHub