How to align checkboxes and their labels consistently cross-browsers
Solution 1
Warning! This answer is too old and doesn't work on modern browsers.
I'm not the poster of this answer, but at the time of writing this, this is the most voted answer by far in both positive and negative votes (+1035 -17), and it's still marked as accepted answer (probably because the original poster of the question is the one who wrote this answer).
As already noted many times in the comments, this answer does not work on most browsers anymore (and seems to be failing to do that since 2013).
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:
- Inputs must be on their own line.
- Checkbox inputs need to align vertically with the label text similarly (if not identically) across all browsers.
- 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 wasvertical-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.
Warning! This answer is too old and doesn't work on modern browsers.
Solution 2
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: inline-block;
padding-right: 10px;
white-space: nowrap;
}
.checkboxes input {
vertical-align: middle;
}
.checkboxes label span {
vertical-align: middle;
}
<form>
<div class="checkboxes">
<label><input type="checkbox"> <span>Label text x</span></label>
<label><input type="checkbox"> <span>Label text y</span></label>
<label><input type="checkbox"> <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;
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><input type="checkbox"> <span>Label text x so long that it will probably wrap so let's see how it goes with the proposed CSS (expected: two lines are aligned nicely)</span></label>
<label><input type="checkbox"> <span>Label text y</span></label>
<label><input type="checkbox"> <span>Label text z</span></label>
</div>
</form>
Solution 3
Working off of One Crayon's solution, I have something that works for me and is simpler:
.font2 {font-family:Arial; font-size:32px} /* Sample font */
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>
<p class="font2">
<label><input type="checkbox"/> Label text</label>
</p>
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...
Update: (Third-Party Edit)
The proper bottom
position depends on font-family and font-size! I found using bottom: .08em;
for checkbox & radio elements is a good general value. I tested it in Chrome/Firefox/IE11 in windows with Arial & Calibri fonts using several small/mid/large font-sizes.
.font2, .font2 input {font-family:Arial; font-size:32px} /* Sample font */
input[type=checkbox], input[type=radio] {
vertical-align: middle;
position: relative;
bottom: .08em; /* this is a better value for different fonts! */
}
<label><input type="checkbox" /> Label text</label>
<p class="font2">
<label><input type="checkbox"/> Label text</label>
</p>
Solution 4
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;
}
Solution 5
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>
html_programmer
Updated on November 18, 2021Comments
-
html_programmer over 2 years
I have multiple routes, split into different files (my app consists of different "modules", which I maintain in separate folders. For each folder, there is an index.js file in which I manage the routes per module, and I require these in the app.js file).
For every route, I will require to check the auth, and pass the loggedIn status to the header of every page://Default variables for the ejs template var options = { loggedIn: true }; res.render("home/home", options);
If the logged in status is true, then the user's name will be displayed. If not, the login / signup labels are displayed.
What is the best way to centralise this, so that I don't need to require the auth script in every of these index.js (route) files?
I need to be able to pass the auth status to the view via the options object (see example).-
volume one over 10 yearsPut each checkbox and label within an <li> element. Add overflow:hidden to the <li> and float the label and checkbox left. Then they all align perfectly fine. Don't put the checkbox within the label element obviously.
-
TheGr8_Nik over 9 yearsI have acieved it by using
height
andline-height
attributes, give a look to jsfiddle.net/wepw5o57/3 -
Profesor08 about 8 years
-
dieter about 5 years2019. still the same issue. still need some hacks to get it work :(
-
YakovL almost 5 years@dieter see my answer, I've explained why hacks are needed and what approach is not hacky: stackoverflow.com/a/56558431/3995261
-
-
perimosocordiae over 15 yearsNot exactly true: The Label-for will allow users to click the label in order to check the checkbox, in addition to simply clicking the checkbox itself. It's quite handy for tying the two elements together.
-
Verlet64 over 15 yearsAs I've said to previous posters who recommended that: I don't like it because it requires unnecessary markup. Also, I tried that markup but it was difficult to prevent the label from wrapping beneath the input (while still having label/input group each on their own lines).
-
Robert C. Barth over 15 yearsSo, instead of "unecessary" markup (used by probably almost everyone), you'd rather have unecessary CSS?
-
Verlet64 over 15 yearsThe problem with wrapping stands. But in general, yes I'd rather have extraneous CSS than markup since the CSS is cached, but the markup may have to be loaded anew for every new page.
-
IDisposable over 15 yearsbless you for using ems instead of pxs.
-
Verlet64 about 15 yearsJust a note for others: this won't work in IE6 because it doesn't support the [type=checkbox] CSS targeting.
-
William Gross over 13 yearsThanks! The "vertical-align: middle" on both the input and the span worked great for me.
-
Greg over 12 yearsCompare: 1 instance of extra CSS -vs- many instances of extra markup.
-
maxspan about 10 yearsalso need to add vertical-align:top or vertical-align:bottom. Depends.. on the position where it needs to get aligned
-
Mariano Desanze over 9 yearsNice! But you should consider copying the HTML and CSS code in here. Answers that depends so much on an external link are discouraged. The link is still valuable to see the results, but I think showing the code in here will help you get more up votes.
-
JonSnow about 9 yearsthe question is: does it work well in all browsers? ;-)
-
robsch over 5 yearsSeems to work as long as the font size is not too large.
-
YakovL almost 5 yearshm, this does look well when the label starts with a lowercase letter, but if it starts with a capital one, it's much worse. Could you add a snippet here?
-
YakovL almost 5 yearsnope, they don't (compare in FireFox and in Chrome, in Chrome the checkboxes are above the baseline), I've explained why
-
YakovL over 4 yearsWhy, you claim the thing that's unsupported even with screenshots from both browsers. It is your job to provide proofs for a claim when you make one, not others' to disprove it. I did compare those and would add the screenshots, but comments don't support adding pictures; you can take a look at pictures in my answer though. This however may differ with browser versions, so providing screenshots with annotations containing browser versions would be helpful.
-
Vladimir Kornea over 4 yearsVisit the page I linked to in different browsers.
-
YakovL over 4 yearsSo I did that, did you? :) Don't you see the difference? imagebin.ca/v/50stCZZGl7Ug imagebin.ca/v/50stNBiv29Ks While in FireFox they are perfectly aligned, in Chrome the checkbox is about the baseline (by the way, you can use mentions via @ if you are interested in quicker replies)
-
Vladimir Kornea over 4 yearsIt's not often people disagree about what they see. I looked at your images at the pixel level, and they are indeed identically aligned. The only difference is that Chrome's checkbox appears to be one pixel shorter because its bottom row of pixels is lighter than the row above it (ie, what the eye sees as the bottom "border" of the checkbox is actually the second to-bottom row of pixels).
-
mustaccio almost 4 yearsYou might want to add an explanation of how this answer is different from the other 47 answers.
-
Adrian Lynch almost 3 yearsWhy the need for flex: none?
-
YakovL over 2 yearssince the answer is outdated and the question is community wiki anyway, let me promote my answer where I'm considering the source of the problem instead of trying to provide some CSS that works only in certain browsers: stackoverflow.com/a/56558431/3995261