0

I have this HTML that I can't change:

<label for="accept">I accept.</label>
<input id="accept" type="checkbox">

Now, I have to use the CSS to move the checkbox to the left and style it with a custom image. What I usually do in CSS, when input goes before label is to make the label act like the checkbox by and hide the actual input:

input[ type=checkbox ] {
  display:none;
  }

input[ type=checkbox ] + label {
  display:inline-block;
  padding-left: 25px;
  cursor: pointer;
  height: 25px;
  background: url('image.png') 0 -5px no-repeat;
}

input[ type=checkbox ]:checked + label {
  background: url('image.png') 0 -40px no-repeat;
}

However, in this case, when I try:

    input[ type=checkbox ] {
      display:none;
      }

    label + input[ type=checkbox ] {
      display:inline-block;
      padding-left: 25px;
      cursor: pointer;
      height: 25px;
      background: url('image.png') 0 -5px no-repeat;
    }

    label + input[ type=checkbox ]:checked {
      background: url('image.png') 0 -40px no-repeat;
    }

not only that it doesn't show the background, but it even unhides the checkbox, so I end up with the default checkbox after the label.

How do I go about doing this without using JavaScript?

cнŝdk
  • 31,391
  • 7
  • 56
  • 78
shebara
  • 1
  • 1
  • 3
  • FYI: In your first code example, you are styling the LABEL element instead of the checkbox. CSS selectors read from right to left. – madr Mar 20 '15 at 10:17
  • thanks for the quick reply. yes, i do know that. the point is to style the label and add the background to the left of it, so it looks and acts like a checkbox – shebara Mar 20 '15 at 10:23
  • are these elements within another element? – Pete Mar 20 '15 at 10:54
  • they are, but i can't style them directly, because there's a whole bunch of elements with the same id (p.form-row), and their number changes because some fields are added or removed depending on the user input. – shebara Mar 20 '15 at 10:59
  • In that case it is not possible (cross browser) with pure css, you would either need to use js to bind an change event or swap the order of the elements in the dom – Pete Mar 20 '15 at 12:08
  • Fiddle with a couple of examples of how to do it with js and jquery library: http://jsfiddle.net/5pbbekwd/ – Pete Mar 20 '15 at 12:18

2 Answers2

0

It is not possible to target the label element using the CSS siblings selector like you try in the second code sample, since CSS selectors are read from right to left.

What you can do is to use a pseudo-element instead, and hide the input element using absolute positioning:

input { 
    position: absolute;
    left: -999em;                /* asuming direction: ltr */
}

input:before { 
    margin-left: 999em;
    float: left;
    content: "";

    /* styles for visual demo */
    height: 25px;
    width: 25px;
    margin-top: -4px;
    background: #ddd;
    border: 1px solid #000;
}

input:checked:before {
    background: #0f0;
}

label { 
    display: inline; 
    padding-left: 35px; 
    line-height: 27px; 
}

Working example on JSFiddle

It is a little tricky to make this work cross-browser since not all browsers allow pseudo-elements in inputs (according to spec, it is correct to not allow it), but it can be done in the browsers which supports it.

Reminder: in cases like this, always try to have the HTML changed first or ask for a compromise for the design (that is, ask if it would be ok to have the checkbox to the right instead of to the left). CSS is quite nasty in the edges, and should not always be the solution just because of the possibility.

Community
  • 1
  • 1
madr
  • 655
  • 4
  • 16
  • yes, thank you, i did pretty much that. someone left an answer with this a few mins ago and deleted it (you, perhaps?): http://jsfiddle.net/yv5uaaLz/ it helped me reach the same conclusion. i can't believe it didn't occur to me before, it was so obvious. anyway, thanks for your help :) – shebara Mar 20 '15 at 11:11
  • No, wasn't me - probably someone wrote it and saw me answer somehow. Please mark answer as solution if it helped you. – madr Mar 20 '15 at 11:15
  • @shebara, I deleted my answer because it only works in chrome (but may not in future) due to html specs - inputs cannot have child elements so before and after pseudo elements won't work in browsers that comply to the standards (chrome doesn't at the moment) – Pete Mar 20 '15 at 11:57
  • thank you @Pete, I upgraded my answer with that information and explained further it would be wise to either try changing the HTML or ask to place input right instead. – madr Mar 20 '15 at 12:08
-3

You can customize default html check box using css. Please have a look at my fiddle. Custom Checkbox Sample

.customCheckBoxDiv {
  position: relative;
  float: left;
}
.customCheckBoxDiv span {
  margin-left: 25px;
  color: #0066cc;
}
.loginCheckBox {
  opacity: 0;
  position: absolute;
  z-index: 1;
  cursor: pointer;
}
.checkLabel {
  width: 13px;
  height: 13px;
  border: 1px solid #00cc00;
  background: #fff;
  position: absolute;
  left: 4px;
  top: 3px;
}
.loginCheckBox:checked + label {
  border: 1px solid #00cc00 !important;
  background: #00cc00 !important;
  box-shadow: inset -2px 0px 0px 0px #fff, inset 2px 0px 0px 0px #fff, inset 0px -2px 0px 0px #fff, inset 0px 2px 0px 0px #fff !important;
}
<div class="customCheckBoxDiv">
  <input type="checkbox" value="None" class="loginCheckBox" name="check" checked />
  <label class="checkLabel"></label> <span>Remember Me</span>

</div>
JitHiN N JOsE
  • 509
  • 4
  • 11