Recently I needed to style the input[type=checkbox] element for a project at work. It used to be notoriously difficult to get default input elements looking the same across multiple browsers. Checking the web showed a utility at csscheckbox.com which helps to generate some code using CSS only, but in using the following HTML structure, it requires the use of id attribute tags in every input element.

<input type="checkbox" id="chk1" /><label for="chk1">Input label</label></code>

The CSS for this is pretty simple because it hides the input box completely and relies on the label to display the state. The “for” attribute is required so the useragent will trigger the state change for the referenced input. As such, you MUST have an “id” tag in your input and the corresponding “for” in your labels. This is ok for a few input checkboxes, but if you have a large list of options, tries the following approach instead.

<label class="chk"><input type="checkbox" />Input label</label>

By wrapping the <input> inside the <label>, you no longer need to specify the “id” and “for” attributes because the <label> always corresponds to the contained <input>. The CSS gets a little bit more complicated though because CSS does not allow you to specify rules for a parent that has a child.

label > input.chk {
// can't specify CSS rule for parent label.
}

Having the label precede the input makes the CSS slightly convoluted. Here is a jsfiddle sample that demonstrates the idea:

label > input[type=checkbox] {
width:20px;
height:20px;
margin:0px;
padding:0px;
vertical-align:middle
}
label.ck > input[type=checkbox]:before {
content:'';
display:inline-block;
width:20px;
height:20px;
background-color:green;
vertical-align:middle;
}

label.ck > input[type=checkbox]:checked:before {
content:'';
display:inline-block;
width:20px;
height:20px;
background-color:black;
vertical-align:middle;
}
label.ck > input:checked {
display:inline-block;
appearance:none;
-webkit-appearance:none;
-moz-appearance:none;
background-color:red;
}