DEV Community

Cover image for Accessibility first: radio buttons
Andrew Bone
Andrew Bone

Posted on • Edited on

Accessibility first: radio buttons

This will be the last element I make, for now, in my accessibility first series. We've made material design switches, material design input boxes and now we're about to make material design radio buttons.

The aim of this short series was to show that you can put accessibility first and still use nice design. Most of these have been quite simple, stylised version of their base element.

What do we want to create?

We'll be making a material design inspired radio button today. As always I'll be avoiding JavaScript, not because it's intrinsically bad but rather I want to lean on the platform as much as possible, this makes a better user experience.

If you don't know radio buttons are grouped by name and you tab to each named group. Tabbing to the group will only select the checked button but you can use the arrow keys to move focus and, subsequently, check the new focused button.

The markup

I have no doubt if you've seen any of my stuff you're used to the style now, label wrapping an input, which I will hide later.

<label class="md_radio">
  <input name="{{group name}}" type="radio" />
  <span class="md_radio__button"></span>
  Radio Button
</label>
Enter fullscreen mode Exit fullscreen mode

Styles

There are so many similarities between the radio button and the switch that I won't go into so much detail with this post but I'll still give you the general flavour.

The states we have to account for are

  • Not checked
  • Checked
  • Disabled
  • Focused

Not checked

We'll do all the setup here too as not checked is the usual default state.

Setup

Here we're just setting some default margins, display type and setting the material font.

@import url(http://fonts.googleapis.com/css?family=Open+Sans);
.md_radio {
  display: inline-flex;
  font-family: "Open Sans";
  align-items: center;
  margin: 5px 0;
}

.md_radio .md_radio__button {
  position: relative;
  cursor: pointer;
  margin: 0 3px;
}
Enter fullscreen mode Exit fullscreen mode

The button

I'm using the ::before and ::after pseudo-classes to make the button, you'll notice my ::after styles are set but are then hidden using scale this is preventing us from having to paint every time a button is checked.

.md_radio .md_radio__button::before,
.md_radio .md_radio__button::after {
  content: '';
  box-sizing: border-box;
  display: block;
  transition: all 100ms cubic-bezier(0.4, 0.0, 0.2, 1);
}

.md_radio .md_radio__button::before {
  height: 1.2em;
  width: 1.2em;
  border-radius: 50%;
  border: 0.15em solid #BDBDBD;
}

.md_radio .md_radio__button::after {
  position: absolute;
  top: 50%;
  left: 50%;
  height: 0.65em;
  width: 0.65em;
  border-radius: 50%;
  transform-origin: 50%, 50%;
  transform: scale(0, 0) translate(-50%, -50%);
  background: #00897B;
}
Enter fullscreen mode Exit fullscreen mode

Material Design Radio Buttons Not checked

Checked

Checked is super simple for this example, we want to scale up ::after and change the border colour of ::before and that's it.

.md_radio [type=radio]:checked+.md_radio__button::after {
  transform: scale(1, 1) translate(-50%, -50%);
}

.md_radio [type=radio]:checked+.md_radio__button::before {
  border-color: #00897B;
}
Enter fullscreen mode Exit fullscreen mode

Material Design Radio Buttons Checked

Disabled and focuses

These styles are exactly the same as my switch example so here's the code.

/* Disabled */
.md_radio [type=radio]:disabled+.md_radio__button {
  cursor: not-allowed;
  filter: grayscale(100%);
  opacity: 0.6;
}

/* Focused */
.md_radio [type=radio]:focus+.md_radio__button {
  outline: #5d9dd5 solid 1px;
  box-shadow: 0 0 8px #5e9ed6;
}
Enter fullscreen mode Exit fullscreen mode

Finishing up

Finally, we need to hide our original input I do this by making the position absolute, to take up no space, setting the opacity to 0 and turning off pointer events.

.md_radio [type=radio] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
Enter fullscreen mode Exit fullscreen mode

Thank you for coming along on this journey with me. I hope you can take something away from this an apply it to your own projects.

Top comments (3)

Collapse
 
4lch4 profile image
Devin W. Leaman

I absolutely love these Accessibility First articles, thank you!

A slightly funny side-note, each time you post a picture of the resulting radio button, or whichever element you're building, I inevitably try and click on it. Every. Time. 🤦‍♂️

You'd think by now I'd realize it's an image...

Collapse
 
link2twenty profile image
Andrew Bone

each time you post a picture of the resulting radio button, or whichever element you're building, I inevitably try and click on it.

That will work now 😅

Collapse
 
link2twenty profile image
Andrew Bone

You're very welcome 😁