Skip to main content

User testing

Help us improve this service. Take part in a short online exercise

Label

When to use this component

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

<label class="ons-label" for="some-input" id="label">Label</label>
{% from "components/label/_macro.njk" import onsLabel %}
{{
    onsLabel({
        "id": 'label',
        "for": "some-input",
        "text": 'Label'
    })
}}
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, for example, data attributes
inputType string false If set to ‘radio’ or ‘checkbox’ will add the relevant css for checkboxes or radios, defaults to text input
{% 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="ons-label__description {% if params.inputType is defined and params.inputType %}ons-{{ params.inputType }}__label--with-description{% else %} ons-input--with-description{% endif %}">
              {{- params.description -}}
        </span>
    {%- endset %}

    <label
        class="{% if params.inputType is not defined -%}ons-label{%- endif %}{{- ' ' + params.classes if params.classes else "" -}}{%- if params.description is defined and params.description %} ons-label--with-description{%- endif %} {{- ' ons-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 %}
.ons-label {
  color: inherit;
  display: block;
  font-weight: $font-weight-bold;
  margin-bottom: 0.4rem;

  &__description {
    @extend .ons-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;
  }

  &--white {
    color: $color-white;
  }
}

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 description parameter 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="ons-label ons-label--with-description" for="some-input">Label</label>
<span id="description-hint" class="ons-label__description  ons-input--with-description">An example description</span>
{% from "components/label/_macro.njk" import onsLabel %}
{{
    onsLabel({
        "text": "Label",
        "for": "some-input",
        "description": "An example description"
    })
}}
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, for example, data attributes
inputType string false If set to ‘radio’ or ‘checkbox’ will add the relevant css for checkboxes or radios, defaults to text input
{% 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="ons-label__description {% if params.inputType is defined and params.inputType %}ons-{{ params.inputType }}__label--with-description{% else %} ons-input--with-description{% endif %}">
              {{- params.description -}}
        </span>
    {%- endset %}

    <label
        class="{% if params.inputType is not defined -%}ons-label{%- endif %}{{- ' ' + params.classes if params.classes else "" -}}{%- if params.description is defined and params.description %} ons-label--with-description{%- endif %} {{- ' ons-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 %}
.ons-label {
  color: inherit;
  display: block;
  font-weight: $font-weight-bold;
  margin-bottom: 0.4rem;

  &__description {
    @extend .ons-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;
  }

  &--white {
    color: $color-white;
  }
}

Inline

Set the optional inline parameter to “true” to place the label in front of the input. Should only be used when an input needs to be displayed alongside another element, for example, a sort filter.

<div class="ons-field ons-field--inline">
  <label class="ons-label" for="select">Sort by</label>
  <select id="select" name="select" class="ons-input ons-input--select ons-u-wa--@xxs">
    <option value="best-match" selected>Best match</option>
    <option value="latest">Latest</option>
  </select>
</div>
{% from "components/select/_macro.njk" import onsSelect %}
{{
    onsSelect({
        "id": "select",
        "name": "select",
        "classes": "ons-u-wa--@xxs",
        "label": {
            "text": "Sort by",
            "inline": true
        },
        "options": [
            {
                "value": "best-match",
                "text": "Best match",
                "selected": true
            },
            {
                "value": "latest",
                "text": "Latest"
            }
        ]
    })
}}
Name Type Required Description
id string true The id of the select. This will also be added to the label if a label is specified
classes string false Classes to add to the select.
name string false The name of the select
value string | number false The value of the select. Helpful for setting the preselected value
attributes object false HTML attributes (for example, data attributes) to add to the select
label Label (ref) false Settings for the select label. for will automatically be set to match the select id
options Array<SelectOption> true An array of options for the select
fieldId string false Id for the field
fieldClasses string false Classes for the field
dontWrap boolean false Prevents the select from being wrapped in a field component
error Error (ref) false Configuration for validation errors

SelectOption

Name Type Required Description
text string true The text for the option
value string | number false The value for the option. If not specified the value will be equal to text
selected boolean false Whether the option is selected. Only one option should have this set
disabled boolean false Whether the option should be disabled. Useful for creating a default option that should not be reselectable, for example, “Please select”
{% macro onsSelect(params) %}
    {% from "components/field/_macro.njk" import onsField %}
    {% from "components/label/_macro.njk" import onsLabel %}

    {% call onsField({
        "id": params.fieldId,
        "classes": params.fieldClases,
        "legendClasses": params.legendClasses,
        "dontWrap": params.dontWrap,
        "error": params.error,
        "inline": params.label.inline if params.label is defined and params.label else ''
    }) %}
        {{
            onsLabel({
                "for": params.id,
                "text": params.label.text,
                "description": params.label.description,
                "classes": params.label.classes
            })
        }}
        <select
            id="{{ params.id }}"
            name="{{ params.name }}"
            class="ons-input ons-input--select{% if params.classes %} {{ params.classes }}{% endif %}{% if params.select and params.select.error %} ons-input--error{% endif %}"
            {% if params.value is defined and params.value %}value="{{ params.value}}" {% 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 %}
        >
            {% for option in params.options %}
            <option value="{{ option.value | default(option.text) }}"
                {% if option.id is defined and option.id %}"id"="{{ option.id }}" {% endif %}
                {% if option.selected is defined and option.selected %}selected {% endif %}
                {% if option.disabled is defined and option.disabled %}disabled {% endif %}
                {% if params.attributes is defined and params.attributes %}{% for attribute, value in option.attributes %}{{ attribute }}="{{ value }}"{% endfor %}{% endif %}
            >
                {{- option.text -}}
            </option>
            {% endfor %}
        </select>
    {% endcall %}
{% endmacro %}

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.

<div class="ons-question ons-u-mb-l ons-u-mt-no">
  <div class="ons-question__answer ons-u-mb-m">
    <fieldset class="ons-fieldset">
      <legend class="ons-fieldset__legend ons-u-mb-no">
        <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title ons-u-mb-m">What is your ethnic group or background?</h1>
      </legend>
      <div class="ons-input-items">
        <div class="ons-radios__items">
          <span class="ons-radios__item">
            <span class="ons-radio">
              <input type="radio" id="white" class="ons-radio__input ons-js-radio" value="" name="ethnicity">
              <label class=" ons-radio__label  ons-label--with-description" for="white" id="white-label">White
                <span id="white-label-description-hint" class="ons-label__description ons-radio__label--with-description">Includes British, Northern Irish, Irish, Gypsy, Irish Traveller, Roma or any other White background</span></label>
            </span>
          </span>
          <br>
          <span class="ons-radios__item">
            <span class="ons-radio">
              <input type="radio" id="mixed" class="ons-radio__input ons-js-radio" value="" name="ethnicity">
              <label class=" ons-radio__label  ons-label--with-description" for="mixed" id="mixed-label">Mixed or Multiple ethnic groups
                <span id="mixed-label-description-hint" class="ons-label__description ons-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>
          </span>
          <br>
          <span class="ons-radios__item">
            <span class="ons-radio">
              <input type="radio" id="asian" class="ons-radio__input ons-js-radio" value="" name="ethnicity">
              <label class=" ons-radio__label  ons-label--with-description" for="asian" id="asian-label">Asian or Asian British
                <span id="asian-label-description-hint" class="ons-label__description ons-radio__label--with-description">Includes Indian, Pakistani, Bangladeshi, Chinese or any other Asian background</span></label>
            </span>
          </span>
          <br>
          <span class="ons-radios__item">
            <span class="ons-radio">
              <input type="radio" id="black" class="ons-radio__input ons-js-radio" value="" name="ethnicity">
              <label class=" ons-radio__label  ons-label--with-description" for="black" id="black-label">Black, Black British, Caribbean or African
                <span id="black-label-description-hint" class="ons-label__description ons-radio__label--with-description">Includes Black British, Caribbean, African or any other Black background</span></label>
            </span>
          </span>
          <br>
          <span class="ons-radios__item">
            <span class="ons-radio">
              <input type="radio" id="other" class="ons-radio__input ons-js-radio" value="" name="ethnicity">
              <label class=" ons-radio__label  ons-label--with-description" for="other" id="other-label">Other ethnic group
                <span id="other-label-description-hint" class="ons-label__description ons-radio__label--with-description">Includes Arab or any other ethnic group</span></label>
            </span>
          </span>
        </div>
      </div>
    </fieldset>
  </div>
</div>
{% 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": "ons-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 %}
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
borderless boolean false Removes the border surrounding the input and label
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), Select (ref), Checkboxes (ref) or Radios (ref) false Object with settings for other input, select, checkboxes or radios
otherType string false (true if other provided) Can be set to select, input, checkboxes or radios to set what other input you want in a radio
selectAllChildren boolean false Provide true when using checkboxes otherType to select all other checkboxes upon selecting the reveal checkbox
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
{% 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="ons-radios__items">
        {% for radio in params.radios %}
            {% if params.or is defined and params.or and loop.revindex0 == 0 %}
                <span class="ons-radios__label ons-u-mt-s ons-u-fs-r--b" aria-hidden="true">{{ params.or }}
                </span>
            {% endif %}
            <span class="ons-radios__item{{ " ons-radios__item--no-border" if params.borderless }}">
                <span class="ons-radio{{ " ons-radio--no-border" if params.borderless }}">
                {%  if radio.other is defined and radio.other and radio.other.selectAllChildren is defined and radio.other.selectAllChildren == true %}
                    {% set selectAllClass = ' ons-js-select-all-children' %}
                {% else %}
                    {% set selectAllClass = '' %}
                {% endif %}
                    <input
                            type="radio"
                            id="{{ radio.id }}"
                            class="ons-radio__input ons-js-radio{{ ' ' + radio.classes if radio.classes else '' }}{{ ' ons-js-other' if radio.other else '' }}{{ selectAllClass }}"
                            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": "ons-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="ons-radio__other{{ " " + 'ons-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": ("ons-input--error" if params.error else "") + radio.other.classes | default(''),
                                        "width": radio.other.width | default('auto'),
                                        "attributes": radio.other.attributes,
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'ons-u-fw-n'
                                        },
                                        "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": ("ons-input--error" if params.error else "") + radio.other.classes | default(''),
                                        "label": {
                                            "id": radio.other.id + "-label",
                                            "text": radio.other.label.text,
                                            "classes": 'ons-u-fw-n'
                                        },
                                        "dontWrap": true,
                                        "value": radio.other.value,
                                        "select": {
                                            "error": params.error
                                        }
                                    })
                                }}
                            {% elif otherType == "checkboxes" %}
                                {% from "components/checkboxes/_macro.njk" import onsCheckboxes %}
                                {{
                                    onsCheckboxes({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "checked": radio.other.checked,
                                        "borderless": true,
                                        "legend": radio.other.legend,
                                        "legendClasses": radio.other.legendClasses,
                                        "attributes": radio.other.attributes,
                                        "classes": "ons-js-other-fieldset",
                                        "checkboxes": radio.other.checkboxes,
                                        "autoSelect": radio.other.autoSelect,
                                        "selectAllChildren": radio.other.selectAllChildren
                                    })
                                }}
                            {% elif otherType == "radios" %}
                                {% from "components/radios/_macro.njk" import onsRadios %}
                                {{
                                    onsRadios({
                                        "id": radio.other.id,
                                        "name": radio.other.name,
                                        "borderless": true,
                                        "legend": radio.other.legend,
                                        "legendClasses": radio.other.legendClasses | default('') + ' ons-u-mb-xs',
                                        "attributes": radio.other.attributes,
                                        "classes": "ons-js-other-fieldset",
                                        "radios": radio.other.radios
                                    })
                                }}
                            {% endif %}
                        </span>
                    {% endif %}
                </span>
            </span>
            {% 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": "ons-js-clear-btn ons-u-mt-s ons-u-db-no-js_enabled",
                "variants": ["secondary", "small"]
            }) }}
        <span class="ons-js-clear-radio-alert ons-u-vh" role="alert" aria-live="polite" data-clear="{{ params.clearRadios.ariaClearText }}" data-cleared="{{ params.clearRadios.ariaClearedText }}"></span>
    {% endif %}
    {% endcall %}

{% endmacro %}
.ons-radio {
  @extend .ons-checkbox;

  &__input {
    @extend .ons-checkbox__input;

    background: $color-grey-5;
    border-radius: 50%;
    box-shadow: inset 0 0 0 3px $color-white;

    &:checked {
      background: $color-input;
    }
  }

  &.ons-radio--no-border {
    @extend .ons-checkbox--no-border;
    & > .ons-radio__input {
      @extend .ons-radio__input;
      &:focus,
      &:checked {
        & + .ons-radio__label::before {
          background: none;
          border: none;
          box-shadow: none;
        }
      }

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

  &__label {
    @extend .ons-checkbox__label;

    &--with-description {
      @extend .ons-checkbox__label--with-description;
    }
  }

  &__description {
    @extend .ons-checkbox__description;
  }

  &__other {
    @extend .ons-checkbox__other;
  }

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

.ons-radios {
  &__items {
    @extend .ons-checkboxes__items;
  }

  &__item {
    @extend .ons-checkboxes__item;

    &--no-border {
      @extend .ons-checkboxes__item--no-border;

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

  &__label {
    @extend .ons-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