Grow your CSS skills. Land your dream job.

Last updated on:

Custom Checkboxes and Radio Buttons

The selectors here are specific to Wufoo markup, but the concepts at work can work for any form. The overall idea is that you make the default radio buttons and checkboxes invisible by setting their opacity to zero, and replace them with graphics. Then use the :checked selector to alternate the graphics between their checked and unchecked versions.

/* 
    Hide the original radios and checkboxes
    (but still accessible)
    
    :not(#foo) > is a rule filter to block browsers
                 that don't support that selector from
                 applying rules they shouldn't
       
*/
li:not(#foo) > fieldset > div > span > input[type='radio'], 
li:not(#foo) > fieldset > div > span > input[type='checkbox'] {
    
    /* Hide the input, but have it still be clickable */
    opacity: 0;
    
    float: left;
    width: 18px;
}


li:not(#foo) > fieldset > div > span > input[type='radio'] + label,
li:not(#foo) > fieldset > div > span > input[type='checkbox'] + label {
    margin: 0;
    clear: none;
    
    /* Left padding makes room for image */
    padding: 5px 0 4px 24px;

    /* Make look clickable because they are */
    cursor: pointer;
    
    background: url(off.png) left center no-repeat; 
}

/*
    Change from unchecked to checked graphic
*/
li:not(#foo) > fieldset > div > span > input[type='radio']:checked + label {
    background-image: url(radio.png);
}
li:not(#foo) > fieldset > div > span > input[type='checkbox']:checked + label {
    background-image: url(check.png);
}

Reference URL

Comments

  1. Perhaps you could provide some sample HTML markup, that would be helpful!

  2. Great. I had to resort to Javascript to do the magic. There are some great plug-ins online.

  3. What’s the browser support for this technique?

  4. Permalink to comment#

    I was trying to work out a way to do this just the other day!

    Nice solution, thanks…

  5. Permalink to comment#

    The Wufoo blog page says it works in IE9+, etc. At a glance, the only bits that I can see that prevent it working in IE7/8 are the :checked selectors.

    This solution aims to do everything in CSS, but if you don’t mind a tiny bit of javascript, perhaps you could simulate :checked by detecting this with javascript, and applying an extra CSS class to the relevant elements as necessary. So for example, you could maybe rewrite the last two rules as:

    
    li > fieldset > div > span > input.radio.checked + label {
    li > fieldset > div > span > input.radio.checked + label {
    

    In Wufoo’s case, since users are not allowed to add their own javascript, Wufoo could just add a little bit of javascript to their global JS code which renders on every form…. it wouldn’t really hurt to do so, as all you’d be doing is appending extra class names (e.g. class=”field radio” becomes class=”field radio checked” when it is checked).

    Just an idea anyway!

  6. This solution sounds promising – I’ll try this when I get home as I still haven’t found a good method if achieving custom check boxes yet. I wish HTML5 had made this easier…

  7. Permalink to comment#

    You could also use :before and :after psuedo-elements to style the check/uncheck instead of using images. Sweet snippet, though.

  8. I wish to share a slight different version of this fantastic trick.
    This is the HTML:

    &ltspan>
    &ltinput type="checkbox" name="xxx" checked="checked">
    &ltlabel for="xxx">A label for xxx&lt/label>
    &lt/span>

    And this is the css:

    input[type='radio'], input[type='checkbox'] {
        
        opacity: 0;
        float: left;
        width: 18px;
        height:18px;
        cursor: pointer;
    }
    
    
    input[type='radio'] + label, input[type='checkbox'] + label {
        
    margin: 0;
        margin-left:-18px;
        clear: none;
        padding: 5px 0 4px 24px;
        background: url(off.png) left center no-repeat; 
    }
    
    
    input[type='radio']:checked + label {
        background-image: url(radio.png);
    }
    
    input[type='checkbox']:checked + label {
        background-image: url(check.png);
    }
    

    Note that I used a negative margin-left to make the label be overlapped by the checkbox (or radio button)

    Let me know if there are errors…

  9. Permalink to comment#

    I have implemented this on a mobile site I am working on. It seems that iOS Safari and Android Browsers are not rendering spacing between multiple inputs and labels the same. In Big Browser, spacing looks as expected and you click on the label to trigger the action. On the mentioned mobile devices, clicking above the label is triggering the action.

    This seems to be because the height of the native checkbox is what is affecting the spacing. I was wondering if anyone else has had any trouble implementing this on mobile devices or if there are some ideas on a direction to head to fix.

  10. luqman
    Permalink to comment#

    can you show me the html for this css..?

  11. Permalink to comment#

    nice 1.

    I have found another beautiful example to customize html checkbox control using css, please go through the below link, I hope it will be useful.

    http://www.etechpulse.com/2014/02/on-off-custom-html-checkbox-css-in.html

    Thanks

  12. Mahiba
    Permalink to comment#

    i want change single radio button background image without label.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".