Accessible Styled Form Controls

Switch Component: Radio Buttons

Last updated:

Pattern to create a two option radio button group, visually styled to resemble a switch component.

Pattern Demo

Away message
Signature
Visual design note

The inclusion of two labels makes this switch pattern unique from other single label switch components. The design tends to fall apart a bit if it can't fully fit on a narrow screen, so that should be taken into consideration if implementing this in your own projects.

Ideally there would be a visible overarching label (a legend) to provide better context as to what the switch was for.

Use an appropriate heading element (h1 to h6) within a legend to surface this group as part of the document outline.

Pattern Details

Pattern Markup
<fieldset class="radio-switch">
  <legend>
    Something
  </legend>

  <input type="radio" name="lol" id="public">
  <label for="public">
    On
  </label>

  <input type="radio" name="lol" id="private">
  <label for="private">
    Off
  </label>
</fieldset>

The markup for this component relies on a standard radio button group setup. A fieldset surrounds the radio buttons to provide context as to what these two options refer to. Each input is placed before its label so sibling selectors can be used to modify the state of the switch UI, based on whether the input is :checked or not.

Affects on Screen Reader Announcements?

Being a custom styled radio button group, there's not much for screen readers to get tripped up on here, and testing revealed no abnormal announcements from screen readers.

The only minor concern for a component like this is that it visually looks like a switch component, and switches have slightly different UX behavior associated with them. For example, a visual switch could be an actual role="switch", a checkbox, or a toggle button, all depending on the context in which it is used. Each of these implementations would have a consistent single label, and the state of the component is what changes. This particular pattern doesn't adhere to those setups.

Usage note:

This type of a switch UI is heavily reliant on the idea that there are two visible labels that represent the opposing ends of the switch. Being that the switch has two labels, it would be expected that each label could receive mouse click or a tap to change the state of the switch.

Ideally the switch itself would also allow for mouse click or finger tap to freely toggle the state as well, as that's an expected interaction for a switch UI.

For single label switches, typically a user can focus the switch and toggle it with either Space or Enter keys. With a radio button switch, arrow keys would be used instead, and Space or Enter keys would be largely irrelevant, beyond a screen reader first focusing a radio button in this component, and using such keys to enter forms mode, if their screen reader hadn't entered forms mode already.

Note: due to :focus-within not having full support for older browsers, a pollyfill has been added to this demo.

Continue reading

For additional information about radio button switch components, I suggest reviewing On Designing and Building Toggle Switches, by Sara Soueidan.