Radio button

Create consistent cross-browser and cross-device radio buttons.

You can find here the OUDS Radio button design guidelines.

Overview

Radio buttons allow user to select a single option from a set of mutually exclusive choices.

They are implemented using .control-item-* classes, see below. Browser default radio buttons are replaced with the help of the selector .control-item-indicator[type="radio"].

<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioDefault" name="radioBasic" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioDefault">Default radio button</label>
  </div>
</div>
<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input checked class="control-item-indicator" type="radio" value="" id="radioDefault2" name="radioBasic" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioDefault2">Checked radio button</label>
  </div>
</div>
html
Bootstrap $enable-bootstrap-compatibility: true
<div class="form-check">
  <input class="form-check-input" type="radio" value="" id="checkDefault" name="radioBasicBs" />
  <label class="form-check-label" for="checkDefault">
    Default radio button (Bootstrap compatible)
  </label>
</div>
<div class="form-check">
  <input checked class="form-check-input" type="radio" value="" id="checkChecked" name="radioBasicBs" />
  <label class="form-check-label" for="checkChecked">
    Checked radio button (Bootstrap compatible)
  </label>
</div>
html

Control item

Control item is an abstraction for several non-text input components, like checkbox, radio button and switch, that have similar behavior and layout. It contains an <input /> indicator, a text container for the label and an optional icon.

We use the parent element selector (:has) for all our <input /> states, like :invalid or :disabled. When combined with the .control-item-label class, we can easily style the text for each item based on the <input />’s state.

.control-item-assets-container controls the position of the .control-item-indicator and the optional icon.

.control-item-text-container contains the label and optional helper text and controls their positioning.

.control-item-label extend their clickable area until a .checkbox-standalone, .radio-button-standalone, .switch-standalone or a position: relative; is found in the page hierarchy. This ensures a consistent approach, whatever the DOM is. Consequently, none of the elements next to the label should be interactive.

.control-item-indicator uses customized icons to indicate checked states.

Variants

Divider

To display a divider, add .control-item-divider to a .radio-button-item.

<div class="radio-button-item control-item-divider">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioDivider" name="radioDivider" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioDivider">Default radio button with divider</label>
  </div>
</div>
<div class="radio-button-item control-item-divider">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioDivider2" name="radioDivider" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioDivider2">Checked radio button with divider</label>
  </div>
</div>
html

Icon

The recommended way to use icons is to fill an SVG sprite file, and use currentColor for styling. If really necessary, for example when you have a lot of icons, you can use an icon font. Find out more about using icons.

To display an icon, add .control-item-assets-container with an icon (SVG or font-icon most likely) inside, as a child of a .radio-button-item.

<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioWithSVG" name="radioIcon" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioWithSVG">Default radio button with an SVG icon</label>
  </div>
  <div class="control-item-assets-container">
    <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
      <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
    </svg>
  </div>
</div>
<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioWithIconFont" name="radioIcon" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioWithIconFont">Checked radio button with a font-icon</label>
  </div>
  <div class="control-item-assets-container">
    <span class="icon si si-settings" aria-hidden="true"></span>
  </div>
</div>
html

Additional label

To add critical information to some of the options, add a .radio-button-additional-label as a sibling of a .control-item-label. Make sure the additional label is accessible by adding an aria-describedby attribute to the input.

Additional label

Additional label

<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioAdditionalLabel" aria-describedby="radioAdditionalTextDescription" name="radioAdditionalLabel" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioAdditionalLabel">Default radio button</label>
    <p class="radio-button-additional-label" id="radioAdditionalTextDescription">Additional label</p>
  </div>
</div>
<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioAdditionalLabel2" aria-describedby="radioAdditionalTextDescription2" name="radioAdditionalLabel" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioAdditionalLabel2">Checked radio button</label>
    <p class="radio-button-additional-label" id="radioAdditionalTextDescription2">Additional label</p>
  </div>
</div>
html

Helper text

To display a helper text, add a .control-item-helper as a sibling of a .control-item-label. Make sure the helper text is accessible by adding an aria-describedby attribute to the input.

Additional label and helper text can be combined, but the additional label must come first (visually and in the aria-describedby attribute).

Helper text

Additional label

Helper text

<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioHelperText" aria-describedby="radioAdditionalTextHelper" name="radioTextHelper" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioHelperText">Default radio button</label>
    <p class="control-item-helper" id="radioAdditionalTextHelper">Helper text</p>
  </div>
</div>
<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioHelperText2" aria-describedby="radioAdditionalTextHelper2 radioAdditionalTextDescription3" name="radioTextHelper" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioHelperText2">Checked radio button</label>
    <p class="radio-button-additional-label" id="radioAdditionalTextDescription3">Additional label</p>
    <p class="control-item-helper" id="radioAdditionalTextHelper2">Helper text</p>
  </div>
</div>
html

Outlined

To display outlined radio buttons, add .radio-button-item-outlined to a .radio-button-item. If there is an outlined radio button item in a group, all its siblings should also be outlined.

<div class="radio-button-item radio-button-item-outlined">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioOutlined1" name="radioOutlined" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioOutlined1">Default outlined radio button</label>
  </div>
</div>
<div class="radio-button-item radio-button-item-outlined">
  <div class="control-item-assets-container">
    <input class="control-item-indicator" type="radio" value="" id="radioOutlined2" name="radioOutlined" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioOutlined2">Checked outlined radio button</label>
  </div>
</div>
html

Layout

Default

It's recommended to keep radio button label to no more than three words. When space is limited or when a long label, additional label or helper text is required, the text can wrap, as this is preferable to truncation. The radio button indicator and the icon will remain vertically centered, until the .control-item-assets-container reaches a defined maximum height.

Additional label

Helper text

Radio button indicator and icon will stick to the top area of the component

Also a longer helper text, it will also wrap at some point depending on the component width

<div class="row">
  <div class="col-8 col-md-6 col-xl-5">
    <div class="radio-button-item control-item-divider">
      <div class="control-item-assets-container">
        <input class="control-item-indicator" type="radio" value="" id="radioLayout1" name="radioLayout" aria-describedby="radioLayout1AdditionalLabel radioLayout1Description" />
      </div>
      <div class="control-item-text-container">
        <label class="control-item-label" for="radioLayout1">Label</label>
        <p class="radio-button-additional-label" id="radioLayout1AdditionalLabel">Additional label</p>
        <p class="control-item-helper" id="radioLayout1Description">Helper text</p>
      </div>
      <div class="control-item-assets-container">
        <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
          <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
        </svg>
      </div>
    </div>
    <div class="radio-button-item control-item-divider">
      <div class="control-item-assets-container">
        <input class="control-item-indicator" type="radio" value="" id="radioLayout2" name="radioLayout"  aria-describedby="radioLayout2AdditionalLabel radioLayout2Description" checked />
      </div>
      <div class="control-item-text-container">
        <label class="control-item-label" for="radioLayout2">A longer label for showing behavior in this case</label>
        <p class="radio-button-additional-label" id="radioLayout2AdditionalLabel">Radio button indicator and icon will stick to the top area of the component</p>
        <p class="control-item-helper" id="radioLayout2Description">Also a longer helper text, it will also wrap at some point depending on the component width</p>
      </div>
      <div class="control-item-assets-container">
        <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
          <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
        </svg>
      </div>
    </div>
  </div>
</div>
html

Reverse

To reverse the component, simply add .control-item-reverse to a .radio-button-item.

Additional label

Helper text

Radio button indicator and icon will stick to the top area of the component

Also a longer helper text, it will also wrap at some point depending on the component width

<div class="row">
  <div class="col-8 col-md-6 col-xl-5">
    <div class="radio-button-item control-item-divider control-item-reverse">
      <div class="control-item-assets-container">
        <input class="control-item-indicator" type="radio" value="" id="radioLayoutRev1" name="radioLayoutRev" aria-describedby="radioLayoutRev1AdditionalLabel radioLayoutRev1Description" />
      </div>
      <div class="control-item-text-container">
        <label class="control-item-label" for="radioLayoutRev1">Label with reverse layout</label>
        <p class="radio-button-additional-label" id="radioLayoutRev1AdditionalLabel">Additional label</p>
        <p class="control-item-helper" id="radioLayoutRev1Description">Helper text</p>
      </div>
      <div class="control-item-assets-container">
        <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
          <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
        </svg>
      </div>
    </div>
    <div class="radio-button-item control-item-divider control-item-reverse">
      <div class="control-item-assets-container">
        <input class="control-item-indicator" type="radio" value="" id="radioLayoutRev2" name="radioLayoutRev"  aria-describedby="radioLayoutRev2AdditionalLabel radioLayoutRev2Description" checked />
      </div>
      <div class="control-item-text-container">
        <label class="control-item-label" for="radioLayoutRev2">A longer label with reverse layout for showing behavior in this case</label>
        <p class="radio-button-additional-label" id="radioLayoutRev2AdditionalLabel">Radio button indicator and icon will stick to the top area of the component</p>
        <p class="control-item-helper" id="radioLayoutRev2Description">Also a longer helper text, it will also wrap at some point depending on the component width</p>
      </div>
      <div class="control-item-assets-container">
        <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
          <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
        </svg>
      </div>
    </div>
  </div>
</div>
html
Bootstrap $enable-bootstrap-compatibility: true

Put your radio buttons on the opposite side with the .form-check-reverse modifier class.

<div class="form-check form-check-reverse">
  <input class="form-check-input" type="radio" value="" id="reverseCheck1" name="radioReverseBs" />
  <label class="form-check-label" for="reverseCheck1">
    Default reverse radio button (Bootstrap compatible)
  </label>
</div>
<div class="form-check form-check-reverse">
  <input class="form-check-input" type="radio" value="" id="reverseCheck2" name="radioReverseBs" checked />
  <label class="form-check-label" for="reverseCheck2">
    Checked reverse radio button (Bootstrap compatible)
  </label>
</div>
html

States

Disabled

Add the disabled attribute to the input, then the radio button and the associated <label> are automatically styled to match with a lighter color to help indicate the input’s state.

Additional label

Helper text

<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input disabled class="control-item-indicator" type="radio" value="" id="radioDisabled" name="radioDisabled" aria-describedby="radioDisabledAdditionalLabel radioDisabledDescription"/>
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioDisabled">Default disabled radio button</label>
    <p class="radio-button-additional-label" id="radioDisabledAdditionalLabel">Additional label</p>
    <p class="control-item-helper" id="radioDisabledDescription">Helper text</p>
  </div>
</div>
<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input disabled class="control-item-indicator" type="radio" value="" id="radioCheckedDisabled" name="radioDisabled" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioCheckedDisabled">Checked disabled radio button</label>
  </div>
</div>
html
Bootstrap $enable-bootstrap-compatibility: true
<div class="form-check">
  <input disabled class="form-check-input" type="radio" value="" id="checkDisabled" name="radioDisabledBs" />
  <label class="form-check-label" for="checkDisabled">
    Default disabled radio button
  </label>
</div>
<div class="form-check">
  <input disabled class="form-check-input" type="radio" value="" id="checkCheckedDisabled" name="radioDisabledBs" checked />
  <label class="form-check-label" for="checkCheckedDisabled">
    Checked disabled radio button
  </label>
</div>
html

Read only

To create a read only radio button, the input should be replaced by a span element with role="radio" and aria-disabled="true" attributes. All the radio buttons in the group must be surrounded by a container with role="radiogroup" and aria-readonly="true" attributes. This is the only way to be compliant with ARIA specifications. The radio button will be accessible to keyboard navigation and assistive technologies, thanks to aria-labelledby and tabindex, but other interactions will be prevented.

Default readonly radio button

Additional label

Helper text

Checked readonly radio button

<div role="radiogroup" aria-readonly="true">
  <div class="radio-button-item">
    <div class="control-item-assets-container">
      <span class="control-item-indicator" role="radio" aria-disabled="true" tabindex="0" aria-checked="false" aria-labelledby="radioReadonlyLabel" aria-describedby="radioReadonlyAdditionalLabel radioReadonlyDescription"></span>
    </div>
    <div class="control-item-text-container">
      <p class="control-item-label" id="radioReadonlyLabel">Default readonly radio button</p>
      <p class="radio-button-additional-label" id="radioReadonlyAdditionalLabel">Additional label</p>
      <p class="control-item-helper" id="radioReadonlyDescription">Helper text</p>
    </div>
  </div>
  <div class="radio-button-item">
    <div class="control-item-assets-container">
      <span class="control-item-indicator" role="radio" aria-disabled="true" tabindex="0" aria-checked="true" aria-labelledby="radioReadonlyCheckedLabel"></span>
    </div>
    <div class="control-item-text-container">
      <p class="control-item-label" id="radioReadonlyCheckedLabel">Checked readonly radio button</p>
    </div>
  </div>
</div>
html

Invalid

The invalid state is the equivalent of the ‘Error’ state that you can find in the design specification.

To display an invalid radio button, add .is-invalid to a .control-item-indicator. Please take a look at our Validation page to learn more.

Additional label

Helper text

Helper text

<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator is-invalid" type="radio" value="" name="radioInvalid" id="radioInvalid" aria-describedby="radioInvalidAdditionalLabel radioInvalidDescription" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioInvalid">Default invalid radio button</label>
    <p class="radio-button-additional-label" id="radioInvalidAdditionalLabel">Additional label</p>
    <p class="control-item-helper" id="radioInvalidDescription">Helper text</p>
  </div>
</div>
<div class="radio-button-item">
  <div class="control-item-assets-container">
    <input class="control-item-indicator is-invalid" type="radio" value="" name="radioInvalid" id="radioInvalid2" aria-describedby="radioInvalid2Description" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="radioInvalid2">Checked invalid radio button</label>
    <p class="control-item-helper" id="radioInvalid2Description">Helper text</p>
  </div>
</div>
html
Bootstrap $enable-bootstrap-compatibility: true

To display an invalid radio button, add .is-invalid to a .form-check-input.

<div class="form-check">
  <input class="form-check-input is-invalid" type="radio" value="" id="radioInvalidBootstrap" />
  <label class="form-check-label" for="radioInvalidBootstrap">
    Invalid radio
  </label>
</div>
html

This also works for outlined variant of the component.

<div class="radio-button-item radio-button-item-outlined">
  <div class="control-item-assets-container">
    <input class="control-item-indicator is-invalid" type="radio" value="" name="outlinedInvalid" id="outlinedInvalid1" />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="outlinedInvalid1">Default invalid outlined radio button</label>
  </div>
</div>
<div class="radio-button-item radio-button-item-outlined">
  <div class="control-item-assets-container">
    <input class="control-item-indicator is-invalid" type="radio" value="" name="outlinedInvalid" id="outlinedInvalid2" checked />
  </div>
  <div class="control-item-text-container">
    <label class="control-item-label" for="outlinedInvalid2">Checked invalid outlined radio button</label>
  </div>
</div>
html

Group

If radio buttons belong to a group (e.g., in a form), provide clear context by adding a <legend> element inside a <fieldset> for the group title. Then, screen readers will read the legend before navigating through the radio buttons.

Radio buttons group example

Additional label

Helper text

Additional label

Helper text

<div class="row">
  <fieldset class="col-md-6">
    <legend>Radio buttons group example</legend>
    <div class="radio-button-item control-item-divider">
      <div class="control-item-assets-container">
        <input class="control-item-indicator" type="radio" value="" id="radioGroup1" name="radioGroup" aria-describedby="radioGroup1AdditionalLabel radioGroup1Description" />
      </div>
      <div class="control-item-text-container">
        <label class="control-item-label" for="radioGroup1">Group radio button 1</label>
        <p class="radio-button-additional-label" id="radioGroup1AdditionalLabel">Additional label</p>
        <p class="control-item-helper" id="radioGroup1Description">Helper text</p>
      </div>
      <div class="control-item-assets-container">
        <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
          <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
        </svg>
      </div>
    </div>
    <div class="radio-button-item control-item-divider">
      <div class="control-item-assets-container">
        <input class="control-item-indicator" type="radio" value="" id="radioGroup2" name="radioGroup"  aria-describedby="radioGroup2AdditionalLabel radioGroup2Description" checked />
      </div>
      <div class="control-item-text-container">
        <label class="control-item-label" for="radioGroup2">Group radio button 2</label>
        <p class="radio-button-additional-label" id="radioGroup2AdditionalLabel">Additional label</p>
        <p class="control-item-helper" id="radioGroup2Description">Helper text</p>
      </div>
      <div class="control-item-assets-container">
        <svg width="1rem" height="1rem" fill="currentColor" aria-hidden="true">
          <use xlink:href="/sosh/docs/0.5/assets/img/ouds-web-sprite.svg#heart-empty" />
        </svg>
      </div>
    </div>
  </fieldset>
</div>
html

Standalone

This standalone version is commonly used for building custom components and should not be used on its own. Remember to provide some sort of accessible name for assistive technologies (for instance, using aria-labelledby, a .visually-hidden, aria-label or a second label). See the forms overview accessibility section for details.

For the standalone radio button, we provide a completely different architecture to ease the integration inside your projects.

<label class="radio-button-standalone">
  <input class="control-item-indicator" type="radio" value="" />
  <span class="visually-hidden">Default standalone radio button</span>
</label>
html
Bootstrap $enable-bootstrap-compatibility: true

Be careful when using this, as you must implement the background on hover, focus and active states.

<div>
  <input class="form-check-input" type="radio" value="" aria-label="Default standalone radio button (Bootstrap compatible)" />
</div>
html