How to align checkboxes and their labels consistently cross-browsers

One Crayon Source

This is one of the minor CSS problems that plagues me constantly. How do folks around Stack Overflow vertically align checkboxes and their labels consistently cross-browser? Whenever I align them correctly in Safari (usually using vertical-align: baseline on the input), they're completely off in Firefox and IE. Fix it in Firefox, and Safari and IE are inevitably messed up. I waste time on this every time I code a form.

Here's the standard code that I work with:

<form>
    <div>
        <label><input type="checkbox" /> Label text</label>
    </div>
</form>

I usually use Eric Meyer's reset, so form elements are relatively clean of overrides. Looking forward to any tips or tricks that you have to offer!

htmlcsscross-browseralignmenthtml-form

Answers

answered 10 years ago digitalsanctum #1

try vertical-align: middle

also your code seems like it should be:

<form>
    <div>
        <input id="blah" type="checkbox"><label for="blah">Label text</label>
    </div>
</form>

answered 10 years ago MusiGenesis #2

I usually leave a checkbox unlabeled and then make its "label" a separate element. It's a pain, but there's so much cross-browser difference between how checkboxes and their labels are displayed (as you've noticed) that this is the only way I can come close to controlling how everything looks.

I also end up doing this in winforms development, for the same reason. I think the fundamental problem with the checkbox control is that it is really two different controls: the box and the label. By using a checkbox, you're leaving it up to the implementers of the control to decide how those two elements are displayed next to each other (and they always get it wrong, where wrong = not what you want).

I really hope someone has a better answer to your question.

answered 10 years ago One Crayon #3

After over an hour of tweaking, testing, and trying different styles of markup, I think I may have a decent solution. The requirements for this particular project were:

  1. Inputs must be on their own line.
  2. Checkbox inputs need to align vertically with the label text similarly (if not identically) across all browsers.
  3. If the label text wraps, it needs to be indented (so no wrapping down underneath the checkbox).

Before I get into any explanation, I'll just give you the code:

label {
  display: block;
  padding-left: 15px;
  text-indent: -15px;
}
input {
  width: 13px;
  height: 13px;
  padding: 0;
  margin:0;
  vertical-align: bottom;
  position: relative;
  top: -1px;
  *overflow: hidden;
}
<form>
  <div>
    <label><input type="checkbox" /> Label text</label>
  </div>
</form>

Here is the working example in JSFiddle.

This code assumes that you're using a reset like Eric Meyer's that doesn't override form input margins and padding (hence putting margin and padding resets in the input CSS). Obviously in a live environment you'll probably be nesting/overriding stuff to support other input elements, but I wanted to keep things simple.

Things to note:

  • The *overflow declaration is an inline IE hack (the star-property hack). Both IE 6 and 7 will notice it, but Safari and Firefox will properly ignore it. I think it might be valid CSS, but you're still better off with conditional comments; just used it for simplicity.
  • As best I can tell, the only vertical-align statement that was consistent across browsers was vertical-align: bottom. Setting this and then relatively positioning upwards behaved almost identically in Safari, Firefox and IE with only a pixel or two of discrepancy.
  • The major problem in working with alignment is that IE sticks a bunch of mysterious space around input elements. It isn't padding or margin, and it's damned persistent. Setting a width and height on the checkbox and then overflow: hidden for some reason cuts off the extra space and allows IE's positioning to act very similarly to Safari and Firefox.
  • Depending on your text sizing, you'll no doubt need to adjust the relative positioning, width, height, and so forth to get things looking right.

Hope this helps someone else! I haven't tried this specific technique on any projects other than the one I was working on this morning, so definitely pipe up if you find something that works more consistently.

answered 10 years ago John Topley #4

I've never had a problem with doing it like this:

<form>
  <div>
    <input type="checkbox" id="cb" /> <label for="cb">Label text</label>
  </div>
</form>

answered 10 years ago Bryan A #5

I usually use line height in order to adjust the vertical position of my static text:

label {
  line-height: 18px;
}
input {
  width: 13px;
  height: 18px;
  font-size: 12px;
  line-height: 12px;
}
<form>
  <div>
    <label><input type="checkbox" /> Label text</label>
  </div>
</form>

Hope that helps.

answered 10 years ago Waleed Eissa #6

Try my solution, I tried it in IE 6, FF2 and Chrome and it renders pixel by pixel in all the three browsers.

* {
  padding: 0px;
  margin: 0px;
}
#wb {
  width: 15px;
  height: 15px;
  float: left;
}
#somelabel {
  float: left;
  padding-left: 3px;
}
<div>
  <input id="wb" type="checkbox" />
  <label for="wb" id="somelabel">Web Browser</label>
</div>

answered 10 years ago Nathan Bowers #7

Sometimes vertical-align needs two inline (span, label, input, etc...) elements next to each other to work properly. The following checkboxes are properly vertically centered in IE, Safari, FF, and Chrome, even if the text size is very small or large.

They all float next to each other on the same line, but the nowrap means that the whole label text always stays next to the checkbox.

The downside is the extra meaningless SPAN tags.

.checkboxes label {
  display: block;
  float: left;
  padding-right: 10px;
  white-space: nowrap;
}
.checkboxes input {
  vertical-align: middle;
}
.checkboxes label span {
  vertical-align: middle;
}
<form>
  <div class="checkboxes">
    <label for="x"><input type="checkbox" id="x" /> <span>Label text x</span></label>
    <label for="y"><input type="checkbox" id="y" /> <span>Label text y</span></label>
    <label for="z"><input type="checkbox" id="z" /> <span>Label text z</span></label>
  </div>
</form>

Now, if you had a very long label text that needed to wrap without wrapping under the checkbox, you'd use padding and negative text indent on the label elements:

.checkboxes label {
  display: block;
  float: left;
  padding-right: 10px;
  padding-left: 22px;
  text-indent: -22px;
}
.checkboxes input {
  vertical-align: middle;
}
.checkboxes label span {
  vertical-align: middle;
}
<form>
  <div class="checkboxes">
    <label for="x"><input type="checkbox" id="x" /> <span>Label text x</span></label>
    <label for="y"><input type="checkbox" id="y" /> <span>Label text y</span></label>
    <label for="z"><input type="checkbox" id="z" /> <span>Label text z</span></label>
  </div>
</form>

answered 10 years ago dylanfm #8

This works well for me:

fieldset {
  text-align:left;
  border:none
}
fieldset ol, fieldset ul {
  padding:0;
  list-style:none
}
fieldset li {
  padding-bottom:1.5em;
  float:none;
  clear:left
}
label {
  float:left;
  width:7em;
  margin-right:1em
}
fieldset.checkboxes li {
  clear:both;
  padding:.75em
}
fieldset.checkboxes label {
  margin:0 0 0 1em;
  width:20em
}
fieldset.checkboxes input {
  float:left
}
<form>
  <fieldset class="checkboxes">
    <ul>
      <li>
        <input type="checkbox" name="happy" value="yep" id="happy" />
        <label for="happy">Happy?</label>
      </li>
      <li>
        <input type="checkbox" name="hungry" value="yep" id="hungry" />
        <label for="hungry">Hungry?</label>
      </li>
    </ul>
  </fieldset>
</form>

answered 10 years ago Jeff #9

Yay thanks! This too has been driving me nuts forever.

In my particular case, this worked for me:

input {
    width: 13px;
    height: 13px;
    padding: 0;
    margin:0;
    vertical-align: top;
    position: relative;
    *top: 1px;
    *overflow: hidden;
}
label {
    display: block;
    padding: 0;
    padding-left: 15px;
    text-indent: -15px;
    border: 0px solid;
    margin-left: 5px;
    vertical-align: top;
}

I am using the reset.css which might explain some of the differences, but this seems to work well for me.

answered 10 years ago #10

Working off of One Crayon's solution, I have something that works for me and is simpler:

input[type=checkbox], input[type=radio] {
  vertical-align: middle;
  position: relative;
  bottom: 1px;
}

input[type=radio] {
  bottom: 2px;
}
<label>
  <input type="checkbox">
  Label text
</label>

Renders pixel-for-pixel the same in Safari (whose baseline I trust) and both Firefox and IE7 check out as good. It also works for various label font sizes, big and small. Now, for fixing IE's baseline on selects and inputs...

answered 9 years ago Stijn #11

Just wanted to add to the discussion about the 'for' attribute on labels (slightly offtopic):

Please do supply it, even when it's not necessary, because it's so very convenient to use from javascript:

var label = ...
var input = document.getElementById(label.htmlFor);

That's a lot more convenient than trying to figure out wheter the label has the input nested, or wheter the input is before the label, or after.. etc. And it never hurts to supply it.. so.

Just my 2 cents.

answered 9 years ago Matijs #12

With an input type checkbox wrapped inside the label and floated to the left like so:

<label for="id" class="checkbox">
    <input type="checkbox" id="id">
    <span>The Label</span>
</label>

this worked for me:

label.checkbox {
    display: block;
}
.checkbox input {
    float: left;
    height: 18px;
    vertical-align: middle;
}
.checkbox span {
    float: left;
    line-height: 18px;
    margin: 0 0 0 20px;
}

Make sure the height of the is identical to the line-height of the (blocklevel) .

answered 9 years ago James #13

input {
    margin: 0;
}

actually does the trick

answered 8 years ago Frank Schwieterman #14

One easy thing that seems to work well is to apply a adjust the vertical position of the checkbox with vertical-align. It will still be vary across browsers, but the solution is uncomplicated.

input {
    vertical-align: -2px;
}

Reference

answered 8 years ago rene #15

This is not the best way of going about solving the issue

vertical-align: middle

Adding style="position:relative;top:2px;" to the input box would move it down 2px. So depending on your font size, you can move it along.

answered 8 years ago Bob Fanger #16

position: relative; has some issues in IE with z-index and animations like jQuery's slideUp/slideDown.

CSS:

input[type=checkbox], input[type=radio] {
    vertical-align: baseline;
    position: relative;
    top: 3px;
    margin: 0 3px 0 0;
    padding: 0px;
}
input.ie7[type=checkbox], input.ie7[type=radio] {
    vertical-align: middle;
    position: static;
    margin-bottom: -2px;
    height: 13px;
    width: 13px;
}

jQuery:

$(document).ready(function () {
    if ($.browser.msie && $.browser.version <= 7) {
        $('input[type=checkbox]').addClass('ie7');
        $('input[type=radio]').addClass('ie7');
    }
});

The styling probably needs tweaks depending on the font-size used in <label>

PS:
I use ie7js to make the css work in IE6.

answered 8 years ago albert #17

<fieldset class="checks">
    <legend>checks for whatevers</legend>
    <input type="" id="x" />
    <label for="x">Label</label>
    <input type="" id="y" />
    <label for="y">Label</label>
    <input type="" id="z" />
    <label for="z">Label</label>
</fieldset>

You should wrap form controls grouped together in their own fieldsets anyways, here, it plays the wrappa. set input/label do display:block, input float left, label float right, set your widths, control spacing with left/right margins, align label text accordingly.

so

fieldset.checks {
    width:200px
}
.checks input, .checks label {
    display:block;
}
.checks input {
    float:right;
    width:10px;
    margin-right:5px
}
.checks label {
    float:left;
    width:180px;
    margin-left:5px;
    text-align:left;
    text-indent:5px
}

you probably need to set border, outline and line-height on both as well for cross-browser/media solutions.

answered 7 years ago Rama Subba Reddy M #18

If you use ASP.NET Web Forms you don't need to worry about DIVs and other elements or fixed sizes. We can align the <asp:CheckBoxList> text by setting float:left to the CheckboxList input type in CSS.

Please check the following example code:

.CheckboxList
{
    font-size: 14px;
    color: #333333;
}
.CheckboxList input
{
    float: left;
    clear: both;
}

.ASPX code:

<asp:CheckBoxList runat="server" ID="c1" RepeatColumns="2" CssClass="CheckboxList">
</asp:CheckBoxList>

answered 7 years ago Carlo Pires #19

<form>
    <div>
        <label style="display: inline-block">
            <input style="vertical-align: middle" type="checkbox" />
            <span style="vertical-align: middle">Label text</span>
         </label>
    </div>
</form>

The trick is to use vertical-align only in table cells or inline-block if using label tag.

answered 7 years ago Philip Bevan #20

CSS:

.threeCol .listItem {
    width:13.9em;
    padding:.2em;
    margin:.2em;
    float:left;
    border-bottom:solid #f3f3f3 1px;
}
.threeCol input {
    float:left;
    width:auto;
    margin:.2em .2em .2em 0;
    border:none;
    background:none;
}
.threeCol label {
    float:left;
    margin:.1em 0 .1em 0;
}

HTML:

<div class="threeCol">
    <div class="listItem">
        <input type="checkbox" name="name" id="id" value="checkbox1" />
        <label for="name">This is your checkBox</label>
    </div>
</div>

The above code will place your list items in threecols and just change widths to suit.

answered 6 years ago user966939 #21

I found out one way to do it that gives the same result in almost all browsers. At the very least up-to-date browsers. It works in Firefox, Chrome, Safari, Opera. In IE it will just look almost as if there were no rules applied for inputs or labels (i.e., it'll still have the label a few pixels below the input), so I think it's excusable.

HTML

<label class="boxfix"><input type="radio">Label</label>

CSS

.boxfix {
    vertical-align: bottom;
}
.boxfix input {
    margin: 0;
    vertical-align: bottom;
    position: relative;
    top: 1.999px; /* the inputs are slightly more centered in IE at 1px (they don't interpret the .999 here), and Opera will round it to 2px with three decimals */
}

answered 6 years ago Sunil D. #22

If you're using Twitter Bootstrap, you can just use the checkbox class on the <label>:

<label class="checkbox">
    <input type="checkbox"> Remember me
</label>

answered 5 years ago Patrick #23

I have not completely tested my solution, but it seems to work great.

My HTML is simply:

<label class="checkbox"><input type="checkbox" value="0000">0000 - 0100</label>

I then set all checkboxes to 24px for both height and width. To make the text aligned I make the label's line-height also 24px and assign vertical-align: top; like so:

EDIT: After IE testing I added vertical-align: bottom; to the input and changed the label's CSS. You may find you need a conditional IE css case to sort out padding - but the text and box are inline.

input[type="checkbox"] {
    width: 24px;
    height: 24px;
    vertical-align: bottom;
}
label.checkbox {
    vertical-align: top;
    line-height: 24px;
    margin: 2px 0;
    display: block;
    height: 24px;
}

If anyone finds that this doesn't work, please kindly let me know. Here is it in action (in Chrome and IE - apologies as screenshots were taken on retina and using parallels for IE):

screenshot of checkboxes: Chrome screenshot of checkboxes: IE

answered 5 years ago Geoff Kendall #24

Maybe some folk are making the same mistake I did? Which was... I had set a width for the input boxes, because they were mostly of type 'text' , but then forgotten to over-ride that width for checkboxes - so my checkbox was trying to occupy a lot of excess width and so it was tough to align a label beside it.

.checkboxlabel {
    width: 100%;
    vertical-align: middle;
}
.checkbox {
    width: 20px !important;
}
<label for='acheckbox' class='checkboxlabel'>
    <input name="acheckbox" id='acheckbox' type="checkbox" class='checkbox'>Contact me</label>

Gives clickable labels and and proper alignment as far back as IE6 (using a class selector) and in late versions of Firefox, Safari and Chrome

answered 5 years ago Milche Patern #25

For consistency with form fields across browsers we use : box-sizing: border-box

button, checkbox, input, radio, textarea, submit, reset, search, any-form-field {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

answered 5 years ago MusikAnimal #26

The chosen answer with 400+ upvotes did not work for me in Chrome 28 OSX, probably because it wasn't tested in OSX or that it did work in whatever was around in 2008 when this question was answered.

The times have changed, and new CSS3 solutions are now feasible. My solution uses pseudoelements to create a custom checkbox. So the stipulations (pros or cons, however you look at it) are as follows:

  • Only works in modern browsers (FF3.6+, IE9+, Chrome, Safari)
  • Relies on a custom designed checkbox, that will be rendered exactly the same in every browser/OS. Here I've just chosen some simple colors, but you could always add linear gradients and such to give it more of a bang.
  • Is geared to a certain font/font size, which if changed, you'd simply change the positioning and size of the checkbox to make it appear vertically aligned. If tweaked correctly, the end result should still be near to exactly the same in all browser / operating systems.
  • No vertical-alignment properties, no floats
  • Must use the provided markup in my example, it will not work if structured like the question, however, the layout will essentially look the same. If you want to move things around, you'll have to also move the associated CSS

Your HTML:

<form>
    <div class="checkbox">
        <input id="check_me" type=checkbox />
        <label for="check_me">Label for checkbox</label>
    </div>
</form>

Your CSS:

div.checkbox {
    position: relative;
    font-family: Arial;
    font-size: 13px;
}
label {
    position: relative;
    padding-left: 16px;
}
label::before {
    content :"";
    display: inline-block;
    width: 10px;
    height: 10px;
    background-color: white;
    border: solid 1px #9C9C9C;
    position: absolute;
    top: 1px;
    left: 0px;
}
label::after {
    content:"";
    width: 8px;
    height: 8px;
    background-color: #666666;
    position: absolute;
    left: 2px;
    top: 3px;
    display: none;
}
input[type=checkbox] {
    visibility: hidden;
    position: absolute;
}
input[type=checkbox]:checked + label::after {
    display: block;
}
input[type=checkbox]:active + label::before {
    background-color: #DDDDDD;
}

This solution hides the checkbox, and adds and styles pseudoelements to the label to create the visible checkbox. Because the label is tied to the hidden checkbox, the input field will still get updated and the value will be submitted with the form.

jsFiddle: http://jsfiddle.net/SgXYY/6/

And if you're interested, here's my take on radio buttons: http://jsfiddle.net/DtKrV/2/

Hope someone finds this useful!

answered 5 years ago Web Designer cum Promoter #27

try this code

input[type="checkbox"] {
    -moz-appearance: checkbox;
    -webkit-appearance: checkbox;
    margin-left:3px;
    border:0;
    vertical-align: middle;
    top: -1px;
    bottom: 1px;
    *overflow: hidden;
    box-sizing: border-box; /* 1 */
    *height: 13px; /* Removes excess padding in IE 7 */
    *width: 13px;
    background: #fff;
}

answered 5 years ago gidzior #28

I think this is the easiest way

input {
    position: relative;
    top: 1px;
}

Fiddle

answered 4 years ago NinjaKC #29

So I know this has been answered many times, but I feel I have a way more elegant solution than those that have been provided already. And not only 1 elegant solution, but 2 separate solutions to tickle your fancy. With that said, everything you need to know and see are contained in 2 JS Fiddle's, with comments.


Solution #1 relies on the native "Checkbox" of the given browser, though with a twist... Its contained in a div which is easier to position cross-browser, with an overflow: hidden to chop the excess of a 1px stretched checkbox (this is so you cant see the ugly borders of FF)

Simple HTML: (follow the link to review the css with comments, code block is to satisfy stackoverflow) http://jsfiddle.net/KQghJ/

<label><div class="checkbox"><input type="checkbox" /></div> Label text</label>

Solution #2 uses the "Checkbox Toggle Hack" to toggle the CSS state of a DIV, which has been properly positioned across browser, and setup with a simple sprite for the checkbox unchecked and checked states. All that is needed is to adjust the background-position with said Checkbox Toggle Hack. This, in my opinion, is the more elegant solution as you have more control over your checkboxes & radios, and can guarantee they look the same across browser.

Simple HTML: (follow the link to review the CSS with comments, code block is to satisfy StackOverflow) http://jsfiddle.net/Sx5M2/

<label><input type="checkbox" /><div class="checkbox"></div>Label text</label>

If anyone disagree's with these methods, please leave me a comment, I would love to hear some feedback on why others have not come across these solutions, or if they have, why I see no answers here regarding them? If anyone sees one of these methods fail, it would be nice to see that too, but these have been tested in the latest browsers and rely on HTML / CSS methods that are quite old, and universal as far as I have seen.

answered 4 years ago Vladimir Kornea #30

Hardcode the checkbox's height and width, remove its padding, and make its height plus vertical margins equal to the label's line-height. If the label text is inline, float the checkbox. Firefox, Chrome, and IE7+ all render the following example identically: http://www.kornea.com/css-checkbox-align

answered 4 years ago pokrishka #31

I don't like relative positioning because it makes element rendered above everything else on its level (it can get on top of something if you have complex layout).

I've discovered that vertical-align: sub makes checkboxes look good enough aligned in Chrome, Firefox and Opera. Can't check Safari since I don't have MacOS and IE10 is slightly off, but I've found it to be good enough solution for me.

Another solution might be to try and make specific CSS for every browser and fine-tune it with some vertical-align in %/pixels/EMs: http://css-tricks.com/snippets/css/browser-specific-hacks/

answered 4 years ago Buzogany Laszlo #32

The only perfectly working solution for me is:

input[type=checkbox], input[type=radio] {
    vertical-align: -2px;
    margin: 0;
    padding: 0;
}

Tested today in Chrome, Firefox, Opera, IE 7 and 8. Example: Fiddle

answered 3 years ago Marco Sulla #33

Use simply vertical-align: sub, as pokrishka already suggested.

Fiddle

HTML Code:

<div class="checkboxes">
    <label for="check1">Test</label>
    <input id="check1" type="checkbox"></input>
</div>

CSS Code:

.checkboxes input {
    vertical-align: sub;
}

answered 3 years ago Henrik Erlandsson #34

The following gives pixel-perfect consistency across browsers, even IE9:

The approach is quite sensible, to the point of being obvious:

  1. Create an input and a label.
  2. Display them as block, so you can float them as you like.
  3. Set the height and the line-height to the same value to ensure they center and align vertically.
  4. For em measurements, to calculate the height of the elements, the browser must know the height of the font for those elements, and it must not itself be set in em measurements.

This results in a globally applicable general rule:

input, label {display:block;float:left;height:1em;line-height:1em;}

With font size adaptable per form, fieldset or element.

#myform input, #myform label {font-size:20px;}

Tested in latest Chrome, Safari, and Firefox on Mac, Windows, Iphone, and Android. And IE9.

This method is likely applicable to all input types that are not higher than one line of text. Apply a type rule to suit.

answered 2 years ago Bryan Willis #35

Now that flexbox is supported in all modern browsers, something like this seems like an easier approach to me.

<style>
label {
  display: flex;
  align-items: center;
}
input[type=radio], input[type=checkbox]{
  flex: none;
}
</style>
<form>
  <div>
    <label><input type="checkbox" /> Label text</label>
  </div>
</form>


Here's the complete prefixed version demo:

label {
	display: -webkit-box;
	display: -webkit-flex;
	display: -ms-flexbox;
	display: flex;
	-webkit-box-align: center;
	-webkit-align-items: center;
	-ms-flex-align: center;
	align-items: center;
}
input[type=radio], 
input[type=checkbox] {
	-webkit-box-flex: 0;
	-webkit-flex: none;
	-ms-flex: none;
	flex: none;
	margin-right: 10px; 
}
/* demo only (to show alignment) */
form {
  max-width: 200px
}
<form>
  <label>
    <input type="radio" checked>
    I am an aligned radio and label
  </label>
  <label>
      <input type="checkbox" checked>
    I am an aligned checkbox and label
  </label>
</form>

answered 1 year ago Prime #36

input[type=checkbox]
{
    vertical-align: middle;
} 
<input id="testCheckbox" name="testCheckbox" type="checkbox">
<label for="testCheckbox">I should align</label>

answered 2 months ago Dylan Sharhon #37

Simple solution:

<label style="display:block">
  <input style="vertical-align:middle" type="checkbox">
  <span  style="vertical-align:middle">Label</span>
</label>

Tested in Chrome, Firefox, IE9+, Safari, iOS 9+

comments powered by Disqus