• Molecule
  • CORE COMPONENT
  • Taxonomic name: M-RADIO-SEGMENTED
  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.9.0 (13/07/21)

Radio segmented controls

Segmented controls adapt a standard radio button set to become sliding switches. They allow users to select from a small list (five options or fewer) and are preferable to a dropdown list in these instances, as they keep all options visible.


Design and usage

  • Use to select a mutually exclusive option from a small list (five options or less).
  • Use when exposing short character length selectable Boolean content
  • Use radio inputs for lists of more than five options.
  • Pictorial switches may be used where an icon enhances understanding of option choices.
  • Use only grey and white solid icons for pictorial switches - see style guide for more detailed colour and spacing guidelines.
  • Labels may wrap over two lines.
  • Aria-invalid must be used to indicate when an error has occurred with this element.
  • Aria-describedby must be used to link any help, instructional and/or error text with the element/form fields.
  • Do not use when the user should be able to select more than one item - in that instance use a checkbox.

Examples

Segmented control - Two options

Interactive example

Code example

<fieldset class="m-form-row">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<ul class="m-form-row-group m-form-row-group--option-group m-radio-segmented--2" data-module="m-radio-segmented">
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label"><span class="a-radio__label-inner">...</span></span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label"><span class="a-radio__label-inner">...</span></span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
		</ul>
	</div>
</fieldset>

Segmented control - Three to five options

Interactive example

Code example

<fieldset class="m-form-row">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<ul class="m-form-row-group m-form-row-group--option-group m-radio-segmented--[ 3 to 5 ]" data-module="m-radio-segmented">
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label"><span class="a-radio__label-inner">...</span></span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
			...
		</ul>
	</div>
</fieldset>

Pictorial segmented control

Inline icon images should be made up as a single sprite with a fixed size of 230px x 74px, with the two versions of the individual icons within it being no more than 85px x 74px and centred horizontally at 50px and 165px.

Interactive example

Code example

<fieldset class="m-form-row">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<ul class="m-form-row-group m-form-row-group--option-group m-form-row-group--pictorial [ Modifiers ]" data-module="m-radio-segmented">
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label">
						<span class="a-radio__label-image">
							<img src="..." decoding="async" width="..." height="..." alt="" />
						</span>
						<span class="a-radio__label-inner">...</span>
					</span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
			...
		</ul>
	</div>
</fieldset>

Segmented control valid

Interactive example

Code example

<fieldset class="m-form-row is-valid">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__validation-message">...</p>
		<ul class="m-form-row-group m-form-row-group--option-group [ Modifiers ]" data-module="m-radio-segmented">
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label"><span class="a-radio__label-inner">...</span></span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
			...
		</ul>
	</div>
</fieldset>

Segmented control error

Interactive example

Code example

<fieldset class="m-form-row is-error" aria-invalid="true" aria-describedby="...">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__error-message" id="..."><span class="u-hidden--visually">Error: </span>...</p>
		<ul class="m-form-row-group m-form-row-group--option-group [ Modifiers ]" data-module="m-radio-segmented">
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label"><span class="a-radio__label-inner">...</span></span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
			...
		</ul>
	</div>
</fieldset>

Segmented control disabled

Interactive example

Code example

<fieldset class="m-form-row is-disabled" disabled>
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<ul class="m-form-row-group m-form-row-group--option-group [ Modifiers ]" data-module="m-radio-segmented">
			<li class="m-form-row-group-item m-form-row-group-item--full-width">
				<label class="a-radio" for="...">
					<input class="a-radio__input" type="radio" name="..." id="..." value="..." />
					<span class="a-radio__label"><span class="a-radio__label-inner">...</span></span>
					<span class="a-radio__ui"></span>
				</label>
			</li>
			...
		</ul>
	</div>
</fieldset>

Required segmented control

<fieldset class="m-form-row" aria-required="true">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		...
	</div>
</fieldset>

Development and test

Notes for developers

A radio input should NEVER be used on its own, instead use a checkbox in this situation.

Radios must be contained within their own fieldset and the legend is the question for the group of radios.

Within a group of radios the name attribute must be common between all the radios, but the id remains unique to the page.

When disabling form elements, do not solely rely on the is-disabled class, but ensure that the disabled attribute is also set on the relevant form element or input. If an entire set of form elements is to be disabled, the is-disabled class and disabled attribute should be added directly to the fieldset instead, and not to each individual element within it. However if only one element from the set is disabled, then the class and attribute should be applied to that element only.

If the native form validation needs to be disabled set the novalidate attribute on the form.

Using autocomplete

Users appreciate when websites save them time by automatically filling common fields like names, email addresses and other frequently used fields, plus it helps to reduce potential input errors, especially on virtual keyboards and small devices.

Browsers use many methods to determine which fields they can auto-populate based on previously specified data by the user, and you can give hints to the browser by providing both the name attribute and the autocomplete attribute on each input element.

Further details can be found in the developer notes on the form introduction page.

Accessibility testing

All Framework components have been accessibility tested, including being scanned using AXE. This component will cause rule violations using the standard AXE configuration (as would be seen if using their browser plugin), some of which may well be false positives; see our accessibility page for details on what rules have been excluded for this component and why.

Aria usage for errors and help text

To aid screen reader users in completing forms without error and also with understanding and fixing any errors that have occured, some additional aria attributes are now recommended to be applied across all form fields/rows.

All form row help, explanatory text, form row instructions and form row errors must have a unique id assigned to them and be appropriately linked to either the individual form input or the form row using aria-describedby. This ensures that the help text is read out immediately on focus of the form input/fieldset. When there is more that one item that requires referencing within the aria-describedby attribute the id values must be supplied in the form of a space separated list. For example if there is an error with id of 'err1' and help text with id of 'help1' the value for the aria-describedby attribute would be 'err1 help1'.

All inline form error messages should start with the hidden text 'Error: ' so that when read by out by a screen reader it is immediately clear that the text being read is an error message.

All erroring form fields (or fieldset if a group or radios/checkboxes) must have aria-invalid="true" set on them, ensuring that when a user focus' on an errored form field, the field will be announced as invalid, so the user is then aware that there in an issue that requires fixing.

When linking help or errors, or even adding aria-invalid to the markup careful consideration must be taken as to where it is most appropriate to apply the value. The following rules should be used to decide where the attribute(s) should be applied.

  • Single form field - All attributes should be applied directly to that form field
  • Group of form fields but only one in error or help text applies to only one - Apply the attribute(s) to the only field in error or where the help text applies
  • Group of form field where all in error or the help text applies to all - Apply the attribute(s) to the groups surrounding fieldset (form row)

There may situations where more than one of these rules applies to the overall form row for example a date range where the instruction text applies to both fields so should be linked to the fieldset for the date range but one of the two fields is in error so the error should be linked to just that field not to the fieldset.

Controling the radio segmented controls component programatically

Radio segmented controls can be controlled programatically to select a particular option or clear any current selection. The following methods are available for use:

Method Description
select( '#inputId' ) Selects the input with the corresponding ID.
clear() Clears any current selection.

For example:

document.addEventListener( 'frameworkready', function () {
	FRAMEWORK.require([ 'blocks/m-radio-segmented' ], function ( mRadioSegmentedModule ) {
		var radioSegmentedEl = document.querySelector( '#segmentedTest' ),
			radioSegmentedInstance = mRadioSegmentedModule.initInstance( radioSegmentedEl );		radioSegmentedInstance.select( '#inputId' );
	});
});

Notes for testers

  • In this instance the label for the radio option is the wording directly on the right of the radio option. Clicking / pressing the explanitory text for the group of radio options will not transfer focus to any of the radio options like it would for a text input.
  • The label should be displayed to the right of the radio button and should activate the radio button when selected (as should the radio button itself).
  • It should be really clear which label applies to which radio button by using background shading to group the label and the radio button together.

Classes overview

The following table gives you a quick overview of the CSS classes that can be applied.

Class Outcome Required Applied to Comments
.m-form-row-group Base styling for a group of form inputs Yes .m-form-row__content > ul  
.m-form-row-group--option-group Base styling for a group of radios Yes .m-form-row-group  
.m-radio-segmented--2 Modifier for two radios side by side at desktop   .m-form-row-group  
.m-radio-segmented--3 Modifier for three radios side by side at desktop   .m-form-row-group  
.m-radio-segmented--4 Modifier for four radios side by side at desktop   .m-form-row-group  
.m-radio-segmented--5 Modifier for five radios side by side at desktop   .m-form-row-group  
.m-radio-segmented--short-label-forced Force radios side by side at mobile   .m-form-row-group  
.m-form-row-group--pictorial Modifier for pictorial radio group   .m-form-row-group  
.m-form-row-group-item Base for individual radios Yes .m-form-row-group > li  
.m-form-row-group-item--full-width Modifer to force radios to be full width (not natural width) when not in column system &bnsp; .m-form-row-group-item Only exclude if using a group of standalone checkboxes
.a-radio Additional styles for radios Yes span  
.a-radio__input Additional styles for radios Yes .a-radio > input  
.a-radio__label Styles for the label Yes .a-radio__input + span  
.a-radio__label-image Wrapper to mask inline sprite image   .a-radio__label + span Place inline image within this wrapper to ensure only selected spite image is visible
.a-radio__label-inner Styles in order to keep the label centered when multiple lines are needed Yes .a-radio__label > span  
.a-radio__ui Animations for the radio Yes .a-radio__label + span  

Keyboard operations

TAB

Tabbing to an group of radio should make the radio option clearly visually different so that the focus point on the page is obvious to the user.

SPACE

With focus on the radio option, pressing SPACE will select/de-select the radio option.

CURSOR KEYS

With focus on the radio option, pressing any CURSOR KEY will move the focus to the next/previous option within the radio option group.

Component releases

  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.9.0 (13/07/21)

Latest update:

  • updated: Radio segmented controls can now be controlled programatically to select a particular option or clear any current selection.

Full version history

A full history of changes and enhancements detailing all minor and major updates to the component.

View full version history

Want something new in Framework, or to chat about an issue you're having with it?

Contact the team