Labels, checkboxes and radio buttons
Asked Answered
S

2

5

My web application uses forms laid out as in the example below...

First Name      [____________]
Last Name       [____________]
Gender          () Male  () Female

The markup I use is something like...

<label for="firstName">First Name</label><input type="text" id="firstName" />
<label for="lastName">Last Name</label><input type="text" id="lastName" />
<label>Gender</label>
<fieldset>
  <legend>Gender</legend>
  <input type="radio" name="sex" id="sex-m" value="m">
  <label for="sex-m">Male</label>
  <input type="radio" name="sex" id="sex-f" value="f">
  <label for="sex-f">Female</label>
</fieldset>

I have the following issues that I don't know how to solve...

  1. I want to have the WHOLE GROUP of radio buttons labelled like any other field (as in the diagram above), but there is nothing to link the label to (i.e. nothing for its "for" attribute, since each radio in the group has its own label just for the value of the individual radio button) A label without a "for" attribute will not pass accessibility compliance.

  2. The <legend> element of the fieldset seems to duplicate the function of the label. Is this really necessary?

I had thought about styling the <legend> tag to appear as though it's a label, and dispense with the label altogether for the radio button group, but that seems a bit hacky to me, and will also introduce complexities elsewhere in my code (which relies on <label> elements to do some nifty validation message markup and various other things)

Thanks in advance.

Statuette answered 26/10, 2012 at 3:40 Comment(1)
Free advice. Avoid using radio buttons as much as possible. They are a pain for screen readers users and users with vision problem (scaling issues and agility required to use them).Adamic
Q
8

The first part of Ssollinger's answer is correct:

The code should be:

<label for="firstName">First Name</label><input type="text" id="firstName" />
<label for="lastName">Last Name</label><input type="text" id="lastName" />
<fieldset>
  <legend>Gender</legend>
  <input type="radio" name="sex" id="sex-m" value="m">
  <label for="sex-m">Male</label>
  <input type="radio" name="sex" id="sex-f" value="f">
  <label for="sex-f">Female</label>
</fieldset>

When assistive technology hits the male radio button, most will read as: "Gender: male radio button 1 of 2 not selected."

Then you could use CSS on the fieldset, legend, the labels and inputs. If memory serves correctly fieldsets can be a bear to style, so i might end up adding a <div> to it:

<label for="firstName">First Name</label><input type="text" id="firstName" />
<label for="lastName">Last Name</label><input type="text" id="lastName" />
<fieldset>
  <legend>Gender</legend>
  <div>
  <input type="radio" name="sex" id="sex-m" value="m">
  <label for="sex-m">Male</label>
  <input type="radio" name="sex" id="sex-f" value="f">
  <label for="sex-f">Female</label>
  </div>
</fieldset>

Adding this <div> has no accessibility implications.

Like in the comment in ssollinger's answer, you could dump the fieldset and legend approach, but you would need to build everything to make it accessible, an example of a build out

Quenby answered 26/10, 2012 at 15:16 Comment(6)
Thanks for the advice. Wasn't sure whose answer to accept so I went for Ryan whose response was more complete and less erroneous (sorry ssollinger)Statuette
Frankly, I'm surprised this situation hasn't been encountered more, since the pattern of putting a label with a group of radio buttons is quite standard in the projects I've worked on. Styling the legend to look like a label still seems shonky to me, but the client's insistent on the labels being there and the forms being accessible, and I can't see any other option other than the full-blown aria build-out, which I just don't have the time for. Thanks!Statuette
What situation? Making fieldsets align? it is just how they are structured at a DOM level.Quenby
Thanks, Ryan. Very relevant. The sad part of this approach is that it cannot be used when the label and form are in separate table cells. I'm trying to build code that generates these things and it won't know how wide to make the label column in advance, so I think I have to use a table to let the browser decide. Why couldn't they have made radio work like select: <radio id=r1><option val=1>First</option><option val=2>Second</option></radio>Hare
@Hare yes it can. If you put an id on a form element, and a for attribute on the label, the label calling the id can literally be anywhere on the page, and it is fine. If you need to do something on the fly, I suggest you make a new question.Quenby
That's probably all you can do, but it's funky for for the common layout with labels in the left-hand column and and controls on the right. What's on the left, as the label for the composite radios field? Nothing, since the fieldset legend serves that purpose, making radios visually different from all other field types? Maybe the legend could be styled to appear in the left column while actually being inside the fieldset on the right, but I'd be really wary, even if it worked in some specific browser versions. Bottom line: I don't see any answer that doesn't make radio sets the odd man out.Selfdrive
R
1

I had thought about styling the <legend> tag to appear as though it's a label, and dispense with the label altogether for the radio button group, …

This is the correct way to do it. "Gender" is not a label for anything, the labels for the radio boxes are "male" and "female". "Gender" is the legend of the fieldset which groups the radio buttons together. The correct way to implement this form is to remove the "Gender" label and just leave the fieldset with legend "Gender".

Technically, you could probably add a <div> around the radio buttons and point the for= of the "Gender" label to that, but I'm quite sure that this will cause accessibility problems (haven't tried it with a screen reader though) so I would strongly recommend to get rid of the label for "Gender".

Route answered 26/10, 2012 at 12:55 Comment(1)
no the pointing of the for will not work. The for attribute only looks at form elements. You could use two divs instead of fieldset/legend. The new div acting as the legend would need an id. Then the sex inputs would need to be given the aria-describedby= attribute with the value of the id.Quenby

© 2022 - 2024 — McMap. All rights reserved.