Cookies on ons.gov.uk

Cookies are small files stored on your device when you visit a website. We use some essential cookies to make this website work.

We would like to set additional cookies to remember your settings and understand how you use the site. This helps us to improve our services.

You have accepted all additional cookies. You have rejected all additional cookies. You can change your cookie preferences at any time.

Skip to main content

Ask users for Durations

Overview

This pattern should be used when you need to collect a duration from a user such as asking how long someone has lived at an address.

How to use this pattern

Duration inputs can be created by using the duration component. For example:

Example Duration contents

Nunjucks

{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}

{% call onsQuestion({
    "title": "How long have you lived at this address?",
    "description": "<p>Enter “0” into the years field if you have lived at this address for less than a year</p>",
    "legendIsQuestionTitle": true
}) %}
    {{ onsDuration({
        "id": "address-duration-example",
        "dontWrap": true,
        "field1": {
            "id": "address-duration-years-example",
            "name": "address-duration-years",
            "suffix": {
                "text": "Years",
                "id": "address-duration-years-suffix-example"
            },
            "attributes": {
                "autocomplete": "off"
            }
        },
        "field2": {
            "id": "address-duration-months-example",
            "name": "address-duration-months",
            "suffix": {
                "text": "Months",
                "id": "address-duration-months-suffix-example"
            },
            "attributes": {
                "autocomplete": "off"
            }
        }
    }) }}
{% endcall %}

Nunjucks macro options

NameTypeRequiredDescription
field1Object<DurationField>trueSettings for the first duration field
field2Object<DurationField>falseSettings for the second duration field
idstringfalseThe HTML id attribute for the field. Applied if only a single field is used
dontWrapbooleanfalsePrevents the date inputs from being wrapped in the fieldset component
legendIsQuestionTitlebooleanfalseCreates an h1 inside the legend. Use when the duration is the only fieldset on the page
mutuallyExclusiveMutuallyExclusive (ref)falseSettings object if the duration is a mutually exclusive answer
legendOrLabelstringtrueText content for the <legend>. If only a single field is used, a <label> is created using the value from this parameter
legendClassesstringfalseClasses for the <legend>
descriptionstringfalseThe hint text for the duration fields
errorError (ref)falseSettings for validation errors for the whole component
DurationField
NameTypeRequiredDescription
idstringfalseThe HTML id attribute for the input
namestringfalseThe HTML name attribute for the input
valuestringfalseThe HTML value for the input to set a preset value for the field
suffixobject <InputSuffix>trueSettings for the input suffix
attributesobjectfalseHTML attributes (for example, data attributes) to add to the element
errorbooleanfalseIf set to true will style this specific field as if it has an error
InputSuffix
NameTypeRequiredDescription
textstringtrueThe visible text label for the prefix or suffix, for example, “Minutes“
titlestringfalseThe HTML title attribute for the <abbr> element, required if the visible text label is an abbreviation. Use to write out the long form of an abbreviated prefix or suffix. For example, if text is “mins”, title should be “Minutes”.
idstringtrueThe HTML id of the element used for the prefix or suffix. Used for the input’s aria-labelledby attribute.

HTML

<div class="ons-question ons-u-mb-l">
  <div class="ons-question__answer ons-u-mb-m">
    <fieldset class="ons-fieldset">
      <legend aria-describedBy="legend-description"
        class="ons-fieldset__legend ons-u-mb-no ons-fieldset__legend--with-description">
        <h1 id="fieldset-legend-title" class="ons-fieldset__legend-title">How long have you lived at this address?</h1>
      </legend>
      <div id="legend-description" class="ons-fieldset__description ons-fieldset__description--title ons-u-mb-m">
        <p>Enter “0” into the years field if you have lived at this address for less than a year</p>
      </div>
      <div class="ons-input-items">
        <div class="ons-field-group">
          <div class="ons-field">
            <span class="ons-input-type ons-js-input-container-abbr">
              <span class="ons-input-type__inner">
                <input type="text" id="address-duration-years-example"
                  class="ons-input ons-input--text ons-input-type__input ons-input-number--w-2"
                  aria-labelledby="address-duration-years-suffix-example"
                  aria-labelledby="address-duration-years-example address-duration-years-suffix-example"
                  name="address-duration-years" pattern="[0-9]*" inputmode="numeric" autocomplete="off" />
                <span id="address-duration-years-suffix-example" class="ons-input-type__type ons-js-input-abbr"
                  aria-label="" role="figure">Years</span>
              </span>
            </span>
          </div>
          <div class="ons-field">
            <span class="ons-input-type ons-js-input-container-abbr">
              <span class="ons-input-type__inner">
                <input type="text" id="address-duration-months-example"
                  class="ons-input ons-input--text ons-input-type__input ons-input-number--w-2"
                  aria-labelledby="address-duration-months-suffix-example"
                  aria-labelledby="address-duration-months-example address-duration-months-suffix-example"
                  name="address-duration-months" pattern="[0-9]*" inputmode="numeric" autocomplete="off" />
                <span id="address-duration-months-suffix-example" class="ons-input-type__type ons-js-input-abbr"
                  aria-label="" role="figure">Months</span>
              </span>
            </span>
          </div>
        </div>
      </div>
    </fieldset>
  </div>
</div>

How to check durations

To help users enter a valid duration, you should:

  • check they have entered something in the duration fields
  • check that what they have entered is valid
  • show an error message if they have not entered anything in one of the fields or what they have entered is not valid

Error messages

Use the correct errors pattern and show the error details above the duration fields.

Example Duration Error contents

Nunjucks
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}

{{
    onsDuration({
        "id": "address-duration-error-example",
        "legendOrLabel": 'How long have you lived at this address?',
        "legendClasses": 'ons-u-vh',
        "field1": {
            "id": "address-duration-years-error-example",
            "name": "address-duration-years",
            "suffix": {
                "text": "Years",
                "id": "address-duration-years-suffix-error-example"
            }
        },
        "field2": {
            "id": "address-duration-months-error-example",
            "name": "address-duration-months",
            "suffix": {
                "text": "Months",
                "id": "address-duration-months-suffix-error-example"
            }
        },
        "error": {
            "id": "address-duration-error-example",
            "text": "Enter how long you have lived at this address"
        }
    })
}}
Nunjucks macro options
NameTypeRequiredDescription
field1Object<DurationField>trueSettings for the first duration field
field2Object<DurationField>falseSettings for the second duration field
idstringfalseThe HTML id attribute for the field. Applied if only a single field is used
dontWrapbooleanfalsePrevents the date inputs from being wrapped in the fieldset component
legendIsQuestionTitlebooleanfalseCreates an h1 inside the legend. Use when the duration is the only fieldset on the page
mutuallyExclusiveMutuallyExclusive (ref)falseSettings object if the duration is a mutually exclusive answer
legendOrLabelstringtrueText content for the <legend>. If only a single field is used, a <label> is created using the value from this parameter
legendClassesstringfalseClasses for the <legend>
descriptionstringfalseThe hint text for the duration fields
errorError (ref)falseSettings for validation errors for the whole component
DurationField
NameTypeRequiredDescription
idstringfalseThe HTML id attribute for the input
namestringfalseThe HTML name attribute for the input
valuestringfalseThe HTML value for the input to set a preset value for the field
suffixobject <InputSuffix>trueSettings for the input suffix
attributesobjectfalseHTML attributes (for example, data attributes) to add to the element
errorbooleanfalseIf set to true will style this specific field as if it has an error
InputSuffix
NameTypeRequiredDescription
textstringtrueThe visible text label for the prefix or suffix, for example, “Minutes“
titlestringfalseThe HTML title attribute for the <abbr> element, required if the visible text label is an abbreviation. Use to write out the long form of an abbreviated prefix or suffix. For example, if text is “mins”, title should be “Minutes”.
idstringtrueThe HTML id of the element used for the prefix or suffix. Used for the input’s aria-labelledby attribute.
HTML
<div class="ons-panel ons-panel--error ons-panel--no-title" id="address-duration-error-example">
  <span class="ons-panel__assistive-text ons-u-vh">Error: </span>
  <div class="ons-panel__body">
    <p class="ons-panel__error">
      <strong>Enter how long you have lived at this address</strong>
    </p>
    <fieldset id="address-duration-error-example" class="ons-fieldset">
      <legend class="ons-fieldset__legend ons-u-vh"><span class="ons-fieldset__legend-title ons-u-pb-no">How long have
          you lived at this address?</span></legend>
      <div class="ons-field-group">
        <div class="ons-field">
          <span class="ons-input-type ons-js-input-container-abbr">
            <span class="ons-input-type__inner">
              <input type="text" id="address-duration-years-error-example"
                class="ons-input ons-input--text ons-input-type__input  ons-input--error ons-input-number--w-2"
                aria-labelledby="address-duration-years-suffix-error-example"
                aria-labelledby="address-duration-years-error-example address-duration-years-suffix-error-example"
                name="address-duration-years" pattern="[0-9]*" inputmode="numeric" />
              <span id="address-duration-years-suffix-error-example" class="ons-input-type__type ons-js-input-abbr"
                aria-label="" role="figure">Years</span>
            </span>
          </span>
        </div>
        <div class="ons-field">
          <span class="ons-input-type ons-js-input-container-abbr">
            <span class="ons-input-type__inner">
              <input type="text" id="address-duration-months-error-example"
                class="ons-input ons-input--text ons-input-type__input  ons-input--error ons-input-number--w-2"
                aria-labelledby="address-duration-months-suffix-error-example"
                aria-labelledby="address-duration-months-error-example address-duration-months-suffix-error-example"
                name="address-duration-months" pattern="[0-9]*" inputmode="numeric" />
              <span id="address-duration-months-suffix-error-example" class="ons-input-type__type ons-js-input-abbr"
                aria-label="" role="figure">Months</span>
            </span>
          </span>
        </div>
      </div>
    </fieldset>
  </div>
</div>

If only one of the duration fields is causing a validation error, you can add error styling to just that single field by setting the additional error parameter.

Example Duration Error For Single Field contents

Nunjucks
{% from "components/question/_macro.njk" import onsQuestion %}
{% from "components/duration/_macro.njk" import onsDuration %}

{{ onsDuration({
    "id": "travel-time",
    "legendOrLabel": 'How long do you spend travelling to and from work each day?',
    "legendClasses": 'ons-u-vh',
    "error": {
        "text": "Enter a number of minutes that is less than 60",
        "id": "duration-error"
    },
    "field1": {
        "id": "travel-time-hours",
        "name": "travel-time-hours",
        "suffix": {
            "text": "Hours",
            "id": "address-time-hours-suffix"
        },
        "value": "2"
    },
    "field2": {
        "id": "travel-time-minutes",
        "name": "travel-time-minutes",
        "suffix": {
            "text": "Minutes",
            "id": "address-time-minutes-suffix"
        },
        "value": "60",
        "error": true
    }
}) }}
Nunjucks macro options
NameTypeRequiredDescription
field1Object<DurationField>trueSettings for the first duration field
field2Object<DurationField>falseSettings for the second duration field
idstringfalseThe HTML id attribute for the field. Applied if only a single field is used
dontWrapbooleanfalsePrevents the date inputs from being wrapped in the fieldset component
legendIsQuestionTitlebooleanfalseCreates an h1 inside the legend. Use when the duration is the only fieldset on the page
mutuallyExclusiveMutuallyExclusive (ref)falseSettings object if the duration is a mutually exclusive answer
legendOrLabelstringtrueText content for the <legend>. If only a single field is used, a <label> is created using the value from this parameter
legendClassesstringfalseClasses for the <legend>
descriptionstringfalseThe hint text for the duration fields
errorError (ref)falseSettings for validation errors for the whole component
DurationField
NameTypeRequiredDescription
idstringfalseThe HTML id attribute for the input
namestringfalseThe HTML name attribute for the input
valuestringfalseThe HTML value for the input to set a preset value for the field
suffixobject <InputSuffix>trueSettings for the input suffix
attributesobjectfalseHTML attributes (for example, data attributes) to add to the element
errorbooleanfalseIf set to true will style this specific field as if it has an error
InputSuffix
NameTypeRequiredDescription
textstringtrueThe visible text label for the prefix or suffix, for example, “Minutes“
titlestringfalseThe HTML title attribute for the <abbr> element, required if the visible text label is an abbreviation. Use to write out the long form of an abbreviated prefix or suffix. For example, if text is “mins”, title should be “Minutes”.
idstringtrueThe HTML id of the element used for the prefix or suffix. Used for the input’s aria-labelledby attribute.
HTML
<div class="ons-panel ons-panel--error ons-panel--no-title" id="duration-error">
  <span class="ons-panel__assistive-text ons-u-vh">Error: </span>
  <div class="ons-panel__body">
    <p class="ons-panel__error">
      <strong>Enter a number of minutes that is less than 60</strong>
    </p>
    <fieldset id="travel-time" class="ons-fieldset">
      <legend class="ons-fieldset__legend ons-u-vh"><span class="ons-fieldset__legend-title ons-u-pb-no">How long do you
          spend travelling to and from work each day?</span></legend>
      <div class="ons-field-group">
        <div class="ons-field">
          <span class="ons-input-type ons-js-input-container-abbr">
            <span class="ons-input-type__inner">
              <input type="text" id="travel-time-hours"
                class="ons-input ons-input--text ons-input-type__input ons-input-number--w-2"
                aria-labelledby="address-time-hours-suffix"
                aria-labelledby="travel-time-hours address-time-hours-suffix" name="travel-time-hours" value="2"
                pattern="[0-9]*" inputmode="numeric" />
              <span id="address-time-hours-suffix" class="ons-input-type__type ons-js-input-abbr" aria-label=""
                role="figure">Hours</span>
            </span>
          </span>
        </div>
        <div class="ons-field">
          <span class="ons-input-type ons-js-input-container-abbr">
            <span class="ons-input-type__inner">
              <input type="text" id="travel-time-minutes"
                class="ons-input ons-input--text ons-input-type__input  ons-input--error ons-input-number--w-2"
                aria-labelledby="address-time-minutes-suffix"
                aria-labelledby="travel-time-minutes address-time-minutes-suffix" name="travel-time-minutes" value="60"
                pattern="[0-9]*" inputmode="numeric" />
              <span id="address-time-minutes-suffix" class="ons-input-type__type ons-js-input-abbr" aria-label=""
                role="figure">Minutes</span>
            </span>
          </span>
        </div>
      </div>
    </fieldset>
  </div>
</div>

If all fields are empty

Use “Enter [whatever the duration is]”. For example, “Enter how long you have lived at this address”.

If one of the fields is empty

Use “Enter the number of [whatever the duration is]”.
For example, “Enter the number of years”.

If what is entered in one of the fields is not a number

Use “Enter a number for [invalid field], for example, [appropriate number]”.
For example, “Enter a number for months, for example, 7”.

If what is entered in a field is above the maximum value for that field

Use “Enter a number that is less than [whatever the maximum is for the duration]”.
For example, “Enter a number that is less than 12” for months.

Help improve this page

Let us know how we could improve this page, or share your user research findings. Discuss the ‘Durations’ pattern on GitHub (opens in a new tab)