How to align checkboxes and their labels consistently cross-browsers

前端 未结 30 1790
有刺的猬
有刺的猬 2020-11-22 05:56

This is one of the minor CSS problems that plagues me constantly. How do folks around Stack Overflow vertically align checkboxes and

相关标签:
30条回答
  • 2020-11-22 06:11

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

    0 讨论(0)
  • 2020-11-22 06:12

    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

    0 讨论(0)
  • 2020-11-22 06:13

    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.

    0 讨论(0)
  • 2020-11-22 06:13

    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/

    0 讨论(0)
  • 2020-11-22 06:15

    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;
    }
    <label class="checkbox"><input type="checkbox" value="0000">0000 - 0100</label>
    <label class="checkbox"><input type="checkbox" value="0100">0100 - 0200</label>
    <label class="checkbox"><input type="checkbox" value="0200">0200 - 0300</label>
    <label class="checkbox"><input type="checkbox" value="0300">0300 - 0400</label>

    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

    0 讨论(0)
  • 2020-11-22 06:16

    Let's finally take a look at the source of the problem

    The checkboxes are rendered using images (one may set custom ones via CSS). Here is an (unchecked) checkbox in FireFox, highlighted with DOM inspector:

    And here's the same unstyled checkbox in Chrome:

    You can see the margin (orange); padding is not present (would be shown green). So what's this pseudo-margin on the right and on the bottom of the checkbox? These are parts of the image used for the checkbox. That's why using just vertical-align: middle doesn't really suffice and that's the source of the cross-browser problems.

    So what can we do about this?

    One obvious option is – replace the images! Fortunately, one can do this via CSS and replace those with external images, base64 (in-CSS) images, in-CSS svg or just pseudo-elements. It's a robust (cross-browser!) approach, and here's an example of such adjustment stolen from this question:

    .checkbox-custom {
      opacity: 0;
      position: absolute;
    }
    .checkbox-custom,
    .checkbox-custom-label {
      display: inline-block;
      vertical-align: middle;
      margin: 5px;
      cursor: pointer;
    }
    .checkbox-custom + .checkbox-custom-label:before {
      content: '';
      display: inline-block;
      background: #fff;
      border-radius: 5px;
      border: 2px solid #ffffd;
      vertical-align: middle;
      width: 10px;
      height: 10px;
      padding: 2px;
      margin-right: 10px;
      text-align: center;
    }
    .checkbox-custom:checked + .checkbox-custom-label:before {
      width: 1px;
      height: 5px;
      border: solid blue;
      border-width: 0 3px 3px 0;
      transform: rotate(45deg);
      -webkit-transform: rotate(45deg);
      -ms-transform: rotate(45deg);
      border-radius: 0px;
      margin: 0px 15px 5px 5px;
    }
    <div>
      <input id="checkbox-1" class="checkbox-custom" name="checkbox-1" type="checkbox">
      <label for="checkbox-1" class="checkbox-custom-label">First Choice</label>
    </div>
    <div>
      <input id="checkbox-2" class="checkbox-custom" name="checkbox-2" type="checkbox">
      <label for="checkbox-2" class="checkbox-custom-label">Second Choice</label>
    </div>

    You may want to read some more in-depth articles about such styling like some listed here; it's out of scope of this answer.

    Ok, still what about no-custom-images-or-pseudo-elements solution?

    TL;DR: looks like this won't work, use custom checkbox instead

    First, let's notice that if in other browsers those pseudo-margins inside checkbox icon were arbitrary, there were no consistent solution. To build one, we have to explore the anatomy of such images in existing browsers.

    So what browsers do have the pseudo-margins in checkboxes? I've checked out Chrome 75, Vivaldi 2.5 (Chromium-based), FireFox 54 (don't ask why such outdated), IE 11, Edge 42, Safari ?? (borrowed one for a minute, forgot to check out the version). Only Chrome and Vivaldi has such pseudo-margins (I suspect all Chromium-based browsers as well, like Opera).

    What's the size of those pseudo-margins? To figure this out one can use a zoomed checkbox:

    input {
      zoom: 10;
      box-shadow: 0 0 1px inset #999;
    }
    <input type=checkbox>

    my result is ~7% of width/height and hence 0.9-1.0px in absolute units. The accuracy may be questioned, though: try different values of zoom for the checkbox. In my tests in both Chrome and Vivaldi the relative size of the pseudo-margin is very different at zoom values 10, 20 and at values 11-19 (??):

    scale seems to be more consistent:

    input {
      transform: scale(10) translate(50%, 50%);
      box-shadow: 0 0 1px inset #999;
    }
    <input type=checkbox>

    so probably ~14% and 2px are the correct values.

    Now that we know (?) the size of the pseudo-margin, let's note this is not enough. Are the sizes of the checkbox icons the same for all browsers? Alas! Here's what DOM inspector shows for unstyled checkboxes:

    • FireFox: 13.3px
    • Chromium-based: 12.8px for the whole thing, hence 12.8 (100% - 14%) = 11px for what is visually perceived as checkbox
    • IE 11, Edge: 13px
    • Safari: n/a (these should be compared on the same screen, I believe)

    Now before we discuss any solutions or tricks, let's ask: what is a correct alignment? What are we trying to achieve? To certain point it's a matter of taste, but basically I can think of the following "nice" alignments' aspects:

    text and checkbox on the same baseline (I deliberately don't adjust checkbox size here):

    or have same middle line in terms of lowercase letters:

    or same middle line in terms of capital letters (it's easier to see the difference for different font size):

    and also we have to decide whether the size of the checkbox should be equal to the height of a lowercase letter, a capital letter or something else (bigger, smaller or between lowercase and capital).

    For this discussion let's call an alignment nice if the checkbox is on the same baseline as the text and has the size of a capital letter (a highly arguable choice):

    Now what tools do we have to:

    1. adjust checkbox size
    2. recognize Chromium with its pseudo-margined checkbox and set specific styles
    3. adjust checkbox/label vertical alignment

    ?

    1. Regarding the checkbox size adjustment: there are width, height, size, zoom, scale (have I missed something?). zoom and scale don't allow to set absolute size, so they may help only with adjusting to text size, not set cross-browser size (unless we can write browser-specific rules). size doesn't work with Chrome (did it work with old IE? anyway, it's not that interesting). width and height work in Chrome and other browsers, so we can set a common size, but again, in Chrome it sets the size of the whole image, not the checkbox itself. Note: it is minimum(width, height) which defines a checkbox's size (if width ≠ height, the area outside checkbox square is added to "pseudo-margin").

      An unfortunate thing is, the pseudo-margins in Chrome checkbox are not set to zero for any width and heights, as far as I can see.

    2. I'm afraid there's no reliable CSS-only method these days.

    3. Let's consider vertical alignment. vertical-align can't give consistent results when set to middle or baseline because of the Chrome's pseudo-margin, the only real option to get the same "coordinate system" for all the browsers is to align label and input to the top:

      (on the picture: vertical-align: top, bottom and bottom without box-shadow)

    So what result do we get from this?

    input[type="checkbox"] {
        height: 0.95em;
        width: 0.95em;
    }
    label, input {
        vertical-align: top;
    }
    <label><input type="checkbox">label</label>

    The snippet above works with Chrome (Chromium-based browsers), but other browsers require a smaller size of the checkbox. It seems to be impossible to adjust both the size and vertical alignment in a way that works around Chromium's checkbox image quirk. My final suggestion is: use custom checkboxes instead – and you'll avoid frustration :)

    0 讨论(0)
提交回复
热议问题