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 drop-down 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 drop-down itself may be difficult to read for users with visual impairments.
<div class="ons-field">
<label class="ons-label" for="select">Question topic</label>
<select id="select" name="select" class="ons-input ons-input--select">
<option value="" selected disabled>Select an option</option>
<option value="general">General</option>
<option value="people-who-live-here">People who live here</option>
<option value="visitors">Visitors</option>
<option value="household-accommodation">Household and accommodation</option>
<option value="personal-details">Personal details</option>
<option value="health">Health</option>
<option value="qualifications">Qualifications</option>
<option value="employment">Employment</option>
</select>
</div>
{% from "components/select/_macro.njk" import onsSelect %}
{{
onsSelect({
"id": "select",
"name": "select",
"label": {
"text": "Question topic"
},
"options": [
{
"value": "",
"text": "Select an option",
"disabled": true,
"selected": true
},
{
"value": "general",
"text": "General"
},
{
"value": "people-who-live-here",
"text": "People who live here"
},
{
"value": "visitors",
"text": "Visitors"
},
{
"value": "household-accommodation",
"text": "Household and accommodation"
},
{
"value": "personal-details",
"text": "Personal details"
},
{
"value": "health",
"text": "Health"
},
{
"value": "qualifications",
"text": "Qualifications"
},
{
"value": "employment",
"text": "Employment"
}
]
})
}}
{% 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 %}
Variants
Wide
<div class="ons-field">
<label class="ons-label" for="select-wide">Question topic</label>
<select id="select-wide" name="select" class="ons-input ons-input--select ons-input--block">
<option value="" selected disabled>Select an option</option>
<option value="general">General</option>
<option value="people-who-live-here">People who live here</option>
<option value="visitors">Visitors</option>
<option value="household-accommodation">Household and accommodation</option>
<option value="personal-details">Personal details</option>
<option value="health">Health</option>
<option value="qualifications">Qualifications</option>
<option value="employment">Employment</option>
<option value="gdp">Gross Domestic Product figures for year ending April 2018</option>
</select>
</div>
{% from "components/select/_macro.njk" import onsSelect %}
{{
onsSelect({
"id": "select-wide",
"name": "select",
"classes": "ons-input--block",
"label": {
"text": "Question topic"
},
"options": [
{
"value": "",
"text": "Select an option",
"disabled": true,
"selected": true
},
{
"value": "general",
"text": "General"
},
{
"value": "people-who-live-here",
"text": "People who live here"
},
{
"value": "visitors",
"text": "Visitors"
},
{
"value": "household-accommodation",
"text": "Household and accommodation"
},
{
"value": "personal-details",
"text": "Personal details"
},
{
"value": "health",
"text": "Health"
},
{
"value": "qualifications",
"text": "Qualifications"
},
{
"value": "employment",
"text": "Employment"
},
{
"value": "gdp",
"text": "Gross Domestic Product figures for year ending April 2018"
}
]
})
}}
{% 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 %}
With inline label
<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"
}
]
})
}}
{% 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 %}
How to check drop-down selection
You should check that users have selected one of the drop-down options and show an error message if they have not.
Error messages
Use the correct errors pattern and show the error details above the drop-down.
<div class="ons-panel ons-panel--error ons-panel--no-title" id="select-error">
<span class="ons-u-vh">Error: </span>
<div class="ons-panel__body">
<p class="ons-panel__error">
<strong>Select a question topic</strong>
</p>
<div class="ons-field">
<label class="ons-label" for="select">Question topic</label>
<select id="select" name="select" class="ons-input ons-input--select">
<option value="" selected disabled>Select an option</option>
<option value="general">General</option>
<option value="people-who-live-here">People who live here</option>
<option value="visitors">Visitors</option>
<option value="household-accommodation">Household and accommodation</option>
<option value="personal-details">Personal details</option>
<option value="health">Health</option>
<option value="qualifications">Qualifications</option>
<option value="employment">Employment</option>
</select>
</div>
</div>
</div>
{% from "components/select/_macro.njk" import onsSelect %}
{{
onsSelect({
"id": "select",
"name": "select",
"label": {
"text": "Question topic"
},
"label": {
"text": "Question topic"
},
"options": [
{
"value": "",
"text": "Select an option",
"disabled": true,
"selected": true
},
{
"value": "general",
"text": "General"
},
{
"value": "people-who-live-here",
"text": "People who live here"
},
{
"value": "visitors",
"text": "Visitors"
},
{
"value": "household-accommodation",
"text": "Household and accommodation"
},
{
"value": "personal-details",
"text": "Personal details"
},
{
"value": "health",
"text": "Health"
},
{
"value": "qualifications",
"text": "Qualifications"
},
{
"value": "employment",
"text": "Employment"
}
],
"error": {
"id": "select-error",
"text": "Select a question topic",
"dsExample": isPatternLib
}
})
}}
{% 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 %}
If a drop-down option has not been selected
Use “Select [whatever topic the drop-down is asking for]”.
For example, “Select a question topic”.
Help improve this component
Let us know how we could improve this component or share your user research findings. Discuss the ‘Select’ component on GitHub