Skip to main content

Select

These should never be used for short lists of items that could be better served by using radio options.

Use with caution

GDS advise against using dropdown select boxes as they have poor accessibility and can be cumbersome to use on a mobile device.

They hide the choices and can confuse users as they may not understand what they’re being asked before they see the answers by interacting with the element.

Where large lists are involved, some users may be unaware that they can scroll through the entire list to find the appropriate answer.

Because the expanded list cannot be styled, this may cause usability issues where the dropdown itself may be difficult to read for users with visual impairments.

<div class="field">
  <label class="label  " for="select">Select your favourite cartoon character
  </label>
  <select id="select" name="select" class="input input--select ">
    <option value="" selected disabled>Select an option</option>
    <option value="bart">Bart Simpson</option>
    <option value="homer">Homer Simpson</option>
    <option value="marge">Marge Simpson</option>
    <option value="lisa">Lisa Simpson</option>
    <option value="maggie">Maggie Simpson</option>
    <option value="ned">Ned Flanders</option>
    <option value="7-dwarves">The 7 Dwarves: Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc</option>
  </select>
</div>
Nunjucks macro options
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, e.g. “Please select”
{% from "components/select/_macro.njk" import onsSelect %}
{{
    onsSelect({
        "id": "select",
        "name": "select",
        "label": {
            "text": "Select your favourite cartoon character"
        },
        "options": [
            {
                "value": "",
                "text": "Select an option",
                "disabled": true,
                "selected": true
            },
            {
                "value": "bart",
                "text": "Bart Simpson"
            },
            {
                "value": "homer",
                "text": "Homer Simpson"
            },
            {
                "value": "marge",
                "text": "Marge Simpson"
            },
            {
                "value": "lisa",
                "text": "Lisa Simpson"
            },
            {
                "value": "maggie",
                "text": "Maggie Simpson"
            },
            {
                "value": "ned",
                "text": "Ned Flanders"
            },
            {
                "value": "7-dwarves",
                "text": "The 7 Dwarves: Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc"
            }
        ]
    })
}}

{% 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,
        "legendIsPageTitle": params.legendIsPageTitle,
        "error": params.error
    }) %}
        {{
            onsLabel({
                "for": params.id,
                "text": params.label.text,
                "description": params.label.description,
                "classes": params.label.classes
            })
        }}
        <select
            id="{{ params.id }}"
            name="{{ params.name }}"
            class="input input--select {{ params.classes }}"
            {% 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 %}

Variants

Wide

<div class="field">
  <label class="label  " for="select-wide">Select your favourite cartoon character
  </label>
  <select id="select-wide" name="select" class="input input--select input--block">
    <option value="" selected disabled>Select an option</option>
    <option value="bart">Bart Simpson</option>
    <option value="homer">Homer Simpson</option>
    <option value="marge">Marge Simpson</option>
    <option value="lisa">Lisa Simpson</option>
    <option value="maggie">Maggie Simpson</option>
    <option value="ned">Ned Flanders</option>
    <option value="7-dwarves">The 7 Dwarves: Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc</option>
  </select>
</div>
Nunjucks macro options
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, e.g. “Please select”
{% from "components/select/_macro.njk" import onsSelect %}
{{
    onsSelect({
        "id": "select-wide",
        "name": "select",
        "label": {
            "text": "Select your favourite cartoon character"
        },
        "classes": "input--block",
        "options": [
            {
                "value": "",
                "text": "Select an option",
                "disabled": true,
                "selected": true
            },
            {
                "value": "bart",
                "text": "Bart Simpson"
            },
            {
                "value": "homer",
                "text": "Homer Simpson"
            },
            {
                "value": "marge",
                "text": "Marge Simpson"
            },
            {
                "value": "lisa",
                "text": "Lisa Simpson"
            },
            {
                "value": "maggie",
                "text": "Maggie Simpson"
            },
            {
                "value": "ned",
                "text": "Ned Flanders"
            },
            {
                "value": "7-dwarves",
                "text": "The 7 Dwarves: Grumpy, Happy, Sleepy, Bashful, Sneezy, Dopey, Doc"
            }
        ]
    })
}}

{% 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,
        "legendIsPageTitle": params.legendIsPageTitle,
        "error": params.error
    }) %}
        {{
            onsLabel({
                "for": params.id,
                "text": params.label.text,
                "description": params.label.description,
                "classes": params.label.classes
            })
        }}
        <select
            id="{{ params.id }}"
            name="{{ params.name }}"
            class="input input--select {{ params.classes }}"
            {% 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 %}

Research on this component

If you have conducted any user research using this component, please feed back your findings via the Design System forum 

Design System forum

Discuss ‘Select’ on GitHub