Radio/checkbox alignment in HTML/CSS

Viewed 257937

What is the cleanest way to align properly radio buttons / checkboxes with text? The only reliable solution which I have been using so far is table based:

<table>
<tr>
    <td><input type="radio" name="opt"></td>
    <td>Option 1</td>
</tr>
<tr>
    <td><input type="radio" name="opt"></td>
    <td>Option 2</td>
</tr>
</table>

This may be frown upon by some. I’ve just spent some time (again) investigating a tableless solution but failed. I’ve tried various combinations of floats, absolute/relative positioning and similar approaches. Not only that they mostly relied silently on an estimated height of the radio buttons / checkboxes, but they also behaved differently in different browsers. Ideally, I would like to find a solution which does not assume anything about sizes or special browser quirks. I’m fine with using tables, but I wonder where there is another solution.

13 Answers

I think I have finally solved the problem. One commonly recommended solution is to use vertical-align: middle:

<input type="radio" style="vertical-align: middle"> Label

The problem, however, is that this still produces visible misalignments even though it should theoretically work. The CSS2 specification says that:

vertical-align: middle: Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.

So it should be in the perfect centre (the x-height is the height of the character x). However, the problem seems to be caused by the fact browsers commonly add some random uneven margins to radio buttons and checkboxes. One can check, for instance in Firefox using Firebug, that the default checkbox margin in Firefox is 3px 3px 0px 5px. I'm not sure where it comes from, but the other browsers seem to have similar margins as well. So to get a perfect alignment, one needs to get rid of these margins:

<input type="radio" style="vertical-align: middle; margin: 0px;"> Label

It is still interesting to note that in the table based solution the margins are somehow eaten and everything aligns nicely.

The following works in Firefox and Opera (sorry, I do not have access to other browsers at the moment):

<div class="form-field">
    <input id="option1" type="radio" name="opt"/>
    <label for="option1">Option 1</label>
</div>

The CSS:

.form-field * {
    vertical-align: middle;
}

I wouldn't use tables for this at all. CSS can easily do this.

I would do something like this:

   <p class="clearfix">
      <input id="option1" type="radio" name="opt" />
      <label for="option1">Option 1</label>
   </p>

p { margin: 0px 0px 10px 0px; }
input { float: left; width: 50px; }
label { margin: 0px 0px 0px 10px; float: left; }

Note: I have used the clearfix class from : http://www.positioniseverything.net/easyclearing.html

.clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}

.clearfix {display: inline-block;}

/* Hides from IE-mac \*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */

This is a bit of a hack but this CSS seems to get it working very nicely in all browsers the same as using tables (apart from chrome)

input[type=radio] { vertical-align: middle; margin: 0; *margin-top: -2px; }
label { vertical-align: middle; }
@media screen and (-webkit-min-device-pixel-ratio:0) {
 input[type=radio] { margin-top: -2px; }
}

Make sure you use labels with your radios for it to work. i.e.

<option> <label>My Radio</label>

If your label is long and goes on multiple rows setting the width and display:inline-block will help.

.form-field * {
  vertical-align: middle;
}
.form-field input {
  clear:left;
}
.form-field label { 
  width:200px;
  display:inline-block;
}

<div class="form-field">
    <input id="option1" type="radio" name="opt" value="1"/>
    <label for="option1">Option 1 is very long and is likely to go on two lines.</label>
    <input id="option2" type="radio" name="opt" value="2"/>
    <label for="option2">Option 2 might fit into one line.</label>
</div>
Related