Radio Group
A radio group is a group of radio buttons that allows the user to select one option from a list of options. No more than one radio button in the group may be checked at a time.
A radio group may be implemented using semantic HTML radio buttons within a <fieldset>
element (recommended) or
using non-semantic HTML elements where the radio group container has a role of radiogroup
and the radio buttons
have a role of radio
.
Role
A group of radio buttons must be enclosed within a container element. The container element must have a role of radiogroup
unless semantic HTML radio buttons are used.
Accessibility label
The container element must have an accessible label. If using a <fieldset>
element, the <legend>
element will be used.
When using non-semantic HTML elements, an accessible label should be provided using the aria-labelledby
attribute that points
to an element that contains the visible label text. If there is not visible label then the aria-label
attribute should be used.
Radio group has radios
A radio group container must contain descendants with a role of radio
or semantic HTML radio buttons.
Forbidden interactive children
Aside from radio buttons, a radio group must not contain any interactive children such as links or buttons. Such children would be inaccessible to screen reader users since they will be excluded from the accessibility tree.
Radios accessibility labels
Each radio button in the group must have an accessible name. Semantic HTML radio buttons may use an associated <label>
element - the
radio button input may either be nested within the <label>
element or the for
attribute may be used to associate the <label>
with
the radio button input. When using non-semantic HTML elements, a visible text node contained within the element with role radio
may
serve as the accessible name otherwise the either the aria-label
attribute or aria-labelledby
attribute may be used to provide an
accessible name.
1<!-- A radio group using semantic HTML radio buttons -->2<fieldset>3 <legend>Radio Group</legend>4 <label><input type="radio" name="radio-group" id="radio1" value="radio1" checked />Radio 1</label>5 <label><input type="radio" name="radio-group" id="radio2" value="radio2" />Radio 2</label>6 <label><input type="radio" name="radio-group" id="radio3" value="radio3" />Radio 3</label>7</fieldset>89<!-- A radio group using non-semantic HTML elements -->10<div role="radiogroup" aria-labelledby="radiogroup-label">11 <span id="radiogroup-label">Radio Group</span>12 <div role="radio" id="radio1" aria-checked="true" tabindex="0">Radio 1</div>13 <div role="radio" id="radio2" aria-checked="false" tabindex="-1">Radio 2</div>14 <div role="radio" id="radio3" aria-checked="false" tabindex="-1">Radio 3</div>15</div>
Set size
Optionally, the aria-setsize
attribute may be used to indicate the number of radio buttons in the group. If the aria-setsize
attribute
is used, then it should be set to the number of radio buttons in the group. The aria-setsize
attribute must be set on the radio buttons
themselves, not the container and it should be consistent across all radio buttons in the group.
Set position
Optionally, the aria-posinset
attribute may be used to indicate the position of a radio button in the group. If the aria-posinset
attribute
is used, then it should be set to the position of the radio button in the group.
ARIA owns
If the radio group should contain radio buttons that cannot be implemented as descendants of the radio group,
the aria-owns
attribute can be used to indicate that the radio group owns the radio buttons.
However, since the aria-owns
attribute is not supported by some assistive technologies,
it is best practice to avoid it. If it must be used, the aria-owns
attribute should be set
on the radio group and should point to the IDs of the owned radio buttons.
Any elements referenced by the aria-owns
attribute should have a role of radio
.
1<div role="radiogroup" aria-labelledby="radiogroup-label" aria-owns="radio1 radio2 radio3">2 <span id="radiogroup-label">Radio Group</span>3</div>4<div role="radio" id="radio1" aria-checked="true" tabindex="0">Radio 1</div>5<div role="radio" id="radio2" aria-checked="false" tabindex="-1">Radio 2</div>6<div role="radio" id="radio3" aria-checked="false" tabindex="-1">Radio 3</div>
Checked radios
At any time, only one radio button in the group may be checked. On initialization it is also permissible for no radio buttons to be checked.
Semantic HTML radio buttons will automatically set the checked
attribute on the radio button that is checked. In non-semantic HTML radio buttons,
if a radio button is checked, the aria-checked
attribute must be set to true
. Unchecked radio buttons should have the aria-checked
attribute
set to false
. Checked radio buttons must be in the focus sequence, see Focus management.
Unreachable group
In semantic HTML radio buttons, if a radio button is disabled, the disabled
attribute must be set on the radio button input. However, it is not
acceptable to have a checked radio button that is disabled or not reacheable by keyboard navigation. This would make the entire radio group
unreachable by keyboard since the checked radio button must receive focus when the radio group receives focus.
1✓ <input type="radio" name="radio-group" id="radio1" value="radio1" checked />2<!-- not reachable by keyboard due to being disabled -->3✗ <input type="radio" name="radio-group" id="radio1" value="radio1" checked disabled />4<!-- not reachable by keyboard due to being excluded from the tab index -->5✗ <input type="radio" name="radio-group" id="radio1" value="radio1" checked tabindex="-1" />
Focus management
When focusing into a radio group where one of the radio buttons is checked, focus should be placed on the checked radio button. If none of the
radio buttons are checked, focus should be placed on the first radio button in the group. Once focus is in the group, the next Tab
key press
should move focus to the next focusable element after the radio group. If the Shift
key is held while pressing Tab
, focus should move to the
previous focusable element before the radio group. In radio groups implemented using native HTML radio buttons, if focus is moved into the radio
group by pressing Shift
+ Tab
and no radio button is checked, it is acceptable for focus to be placed on the last radio button in the group.
For radio groups implemented using semantic HTML radio buttons, the browser will handle focus management. For radio groups implemented using non-semantic HTML elements, there are two options for focus management:
- Make the checked radio button (or first button if no radio is checked) focusable by adding the
tabindex="0"
attribute. Although not strictly required, it is a best practice to explictly make the unchecked radio buttons unfocusable by adding thetabindex="-1"
attribute.
1<div role="radiogroup" aria-labelledby="radiogroup-label">2 <span id="radiogroup-label">Radio Group</span>3 <div role="radio" aria-checked="true" tabindex="0">Radio 1</div>4 <div role="radio" aria-checked="false" tabindex="-1">Radio 2</div>5 <div role="radio" aria-checked="false" tabindex="-1">Radio 3</div>6</div>
- Make the radio group container element focusable by adding the
tabindex="0"
attribute. Use thearia-activedescedant
attribute on the container with the ID of the checked radio button (or first button if no radio is checked). This will cause the browser to move focus to the checked radio button when the radio group container is focused.
1<div role="radiogroup" aria-labelledby="radiogroup-label" tabindex="0" aria-activedescendant="radio1">2 <span id="radiogroup-label">Radio Group</span>3 <div role="radio" id="radio1" aria-checked="true">Radio 1</div>4 <div role="radio" id="radio2" aria-checked="false">Radio 2</div>5 <div role="radio" id="radio3" aria-checked="false">Radio 3</div>6</div>
Once focus is in the radio group, the Arrow
keys may be used to move selection and focus between radio buttons in the group.
- The
ArrowDown
andArrowRight
keys should move focus and change the selection to the next radio button in the group. If focus is on the last radio button in the group, it should loop around to the first radio button. - The
ArrowUp
andArrowLeft
keys should move focus and change the selection to the previous radio button. If focus is on the first radio button in the group, it should loop around to the last radio button.
For radio groups implemented using semantic HTML radio buttons, the browser will handle keyboard navigation. For radio groups implemented using
non-semantic HTML elements, the Arrow
keys may be handled using JavaScript.
1const radios = document.querySelectorAll('[role="radio"]');2const radioGroup = document.querySelector('[role="radiogroup"]');3let index = 0;45// using tabindex6function handleKeyUp(event) {7 const { key } = event;8 if (key === 'ArrowDown' || key === 'ArrowRight') {9 index = index === radios.length - 1 ? 0 : index + 1;10 } else if (key === 'ArrowUp' || key === 'ArrowLeft') {11 index = index === 0 ? radios.length - 1 : index - 1;12 } else {13 return;14 }15 for (let i = 0; i < radios.length; i++) {16 // update tabindex and aria-checked attributes17 radios[i].setAttribute('tabindex', i === index ? '0' : '-1');18 radios[i].setAttribute('aria-checked', i === index);19 }20 // focus the selected radio button21 radios[index].focus();22}2324// using aria-activedescendant25function handleKeyUp(event) {26 const { key } = event;27 if (key === 'ArrowDown' || key === 'ArrowRight') {28 index = index === radios.length - 1 ? 0 : index + 1;29 } else if (key === 'ArrowUp' || key === 'ArrowLeft') {30 index = index === 0 ? radios.length - 1 : index - 1;31 } else {32 return;33 }34 for (let i = 0; i < radios.length; i++) {35 // update aria-checked attribute36 radios[i].setAttribute('aria-checked', i === index);37 }38 // focus the selected radio button and update aria-activedescendant attribute39 radios[index].focus();40 radioGroup.setAttribute('aria-activedescendant', radios[index].id);41}4243radioGroup.addEventListener('keyup', handleKeyUp);
Toolbar radio groups
Radio groups are often used in toolbars. In this case there are some important differences in keyboard navigation:
- The
Arrow
keys should not change the selection, they should only move focus between radio buttons in the group. - The
Space
key should change the selection to the focused radio button if it is unchecked. - Optionally the
Enter
key may also change the selection to the focused radio button if it is unchecked. - When focus is on the last radio button in the group, the
ArrowRight
key should move the focus to the next element in the toolbar rather than looping around to the first radio button in the group. - When focus is on the first radio button in the group, the
ArrowLeft
key should move the focus to the previous element in the toolbar rather than looping around to the last radio button in the group. - Navigation using the
ArrowDown
andArrowUp
keys is optional. If implemented, theArrowDown
key should move focus to the next element and theArrowUp
key should move focus to the previous element.