Many young guns ask about how to style custom checkboxes and radio buttons in forms. I prepared a typical markup, a few lines of CSS and some JavaScript functions (Safari label behavior fix included).
The structure
Each radio button and/or checkbox input element should be surrounded with <label> tags. Here’s the example:
<label class="label_check" for="sample"><input name="sample" id="sample" value="1" type="checkbox" /> Sample Label</label>
<label class="label_radio" for="sample"><input name="sample" id="sample" value="1" type="radio" /> Sample Label</label>
The presentation
We are going to remove inputs far away to the left and instead place a background image to each label. Radios and checkboxes will be toggled, because clicking/spacepressing the corresponding label toggles them on or off.
See the CSS sample:
label.c_off,
label.r_off,
label.c_on,
label.r_on { padding-left: 20px; }
label.c_off input,
label.r_off input,
label.c_on input,
label.r_on input { position: absolute; left: -9999px; }
label.r_off { background: url(radio_off.gif); }
label.c_off { background: url(check_off.gif); }
label.c_on { background: url(check_on.gif); }
label.r_on { background: url(radio_on.gif); }
The behavior
And finally, some JavaScript trickery to handle all the className switching. In Safari, labels are not clickable, hence a few extra Safari speciffic lines.
var d = document;
var safari = (navigator.userAgent.toLowerCase().indexOf('safari') != -1) ? true : false;
var gebtn = function(parEl,child) { return parEl.getElementsByTagName(child); };
onload = function() {
if(!d.getElementById || !d.createTextNode) return;
var ls = gebtn(d,'label');
for (var i = 0; i < ls.length; i++) {
var l = ls[i];
if (l.className.indexOf('label_') == -1) continue;
var inp = gebtn(l,'input')[0];
if (l.className == 'label_check') {
l.className = (safari && inp.checked == true || inp.checked) ? 'label_check c_on' : 'label_check c_off;
l.onclick = check_it;
};
if (l.className == 'label_radio') {
l.className = (safari && inp.checked == true || inp.checked) ? 'label_radio r_on' : 'label_radio r_off';
l.onclick = turn_radio;
};
};
};
var check_it = function() {
var inp = gebtn(this,'input')[0];
if (this.className == 'label_check c_off' || (!safari && inp.checked)) {
this.className = 'label_check c_on';
if (safari) inp.checked = true;
} else {
this.className = 'label_check c_off';
if (safari) inp.checked = false;
};
};
var turn_radio = function() {
var inp = gebtn(this,'input')[0];
if (this.className == 'label_radio r_off' || inp.checked) {
var ls = gebtn(this.parentNode,'label');
for (var i = 0; i < ls.length; i++) {
var l = ls[i];
if (l.className.indexOf('label_radio') == -1) continue;
l.className = 'label_radio r_off';
};
this.className = 'label_radio r_on';
if (safari) inp.checked = true;
} else {
this.className = 'label_radio r_off';
if (safari) inp.checked = false;
};
};
Also, be sure to check the previous post about how to preload all those interface graphics.
Update
Sample web sites: