loading...
Cover image for Accessibility first: radio buttons

Accessibility first: radio buttons

link2twenty profile image Andrew Bone Updated on 惻3 min read

Accessibility first (6 Part Series)

1) Accessibility first: toggle switches 2) Accessibility first: text input 3 ... 4 3) Accessibility first: radio buttons 4) Accessibility first: tabs 5) Accessibility first: DropDown (Select) 6) Accessibility first: Dialog

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>

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;
}

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;
}

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;
}

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;
}

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;
}

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.

Accessibility first (6 Part Series)

1) Accessibility first: toggle switches 2) Accessibility first: text input 3 ... 4 3) Accessibility first: radio buttons 4) Accessibility first: tabs 5) Accessibility first: DropDown (Select) 6) Accessibility first: Dialog

Posted on Dec 6 '18 by:

link2twenty profile

Andrew Bone

@link2twenty

A British Front-end developer, that is passionate about web accessibility.

Discussion

markdown guide
 

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...

 

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 šŸ˜…

 

You're very welcome šŸ˜