1

I'm styling my input[type=radio]'s with CSS, because I need to replace the default radio with an image. Actually what I am doing is hide the input element, and show the styled label with the image background.

To do this I'm using new CSS3 selectors "#myinputradio + label" and "myinputradio:checked + label". All works well using the last versions of each browser (including IE9), but I need to get it working up to IE7.

I can also refer on JQuery, but I'd like to exploit the same CSS selector for JS and CSS3-ready browsers (I have a lot of radio inputs and each one has its own background image, placed from a common sprite).

Is there any way to do this supporting also older browsers?

Here a sample from HTML:

<input id="euro" type="radio" value="euro" checked="" name="currency">
<label for="euro"></label>

And here the CSS used to style it:

#euro + label /*and all other checkboxes*/ {
    display: inline-block;
    width: 37px;
    height: 37px;
    background: url(../img/sprites.png);
}

#euro + label {
    background-position: 1042px 898px;
}

#euro:checked + label {
    background-position: 1108px 898px;
}

If you need more informations, please ask me. Thanks.

Ale A
  • 349
  • 5
  • 16
  • Use JS to add/remove the classname 'checked' when a radio is clicked. Then in CSS also add the rule for .checked in addition to :checked. – Gerben Sep 18 '11 at 13:40

2 Answers2

2

This should work very well (Fiddle: http://jsfiddle.net/p5SNL/):

//Loops through each radio input element
$('input[type="radio"]').each(function(){

    // Checks if the next element is a label, and whether the RADIO element 
    //  has a name or not (a name attribute is required)
    if(/label/i.test($(this).next()[0].tagName) && this.name){

        // Adds an onchange event handler to the RADIO input element
        // THIS FUNCTION will ONLY run if the radio element changes value
        $(this).change(function(){

            // Loop through each radio input element with the a name attribute
            //  which is equal to the current element's name
            $('input[type="radio"][name="'+this.name+'"]').each(function(){

                /*****
                 * The next line is an efficient way to write:
                 * if(this.checked){ // Is this element checked?
                 *     // Adds "labelChecked" class to the next element (label)
                 *     $(this).next().addClass("labelChecked");
                 * } else {
                 *     //Removes "labelChecked" class from next element (label)
                 *     $(this).next().removeClass("labelChecked");
                 * }
                 *****/
                $(this).next()[this.checked?"addClass":"removeClass"]("labelChecked");

                /* Alternatively, setting the CSS background:
                 * CSS background = IF "radio checked?" THEN "green" ELSE "red"
                $(this).next().css("background", this.checked?"green":"red");
                 */
            });

        }); //end of event handler declaration

        //Adds "labelChecked" class to the current element IF it's checked
        if(this.checked) $(this).next().addClass("labelChecked");
        /*Alternative way, setting a CSS background instead of a className:
        if(this.checked) $(this).next().css("background", "green");
         */

    } //end of IF

}); //end of the loop through all RADIO elements

Note that I have deliberately added the wrong for attribute at the last label (fiddle), to show what does (and should) happen when you attach the wrong for attribute to a label.

EDIT

Read the comments for the explanation of the code. I have added an alternative way to define a style inside comments (2x).

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Hi, I've tried it on jsfiddle and it works very well! Thank you. Now I've tried to edit it a bit, applied to my radio inputs, but it does not work [here the edited code](http://paste.pocoo.org/show/myB27eMWJiZC9l2rZZut/). What am I doing wrong? Thank you `:-)` – Ale A Sep 18 '11 at 15:06
  • 1
    See my updated answer: I have added detailled comments. You also had to change the code inside the `onchange` event handler (defined by `$(...).change(function(){ ... })`). – Rob W Sep 18 '11 at 15:46
1

Two issues I see here:

Inline-block

Part of the problem is this bit of code:

#euro + label /*and all other checkboxes*/ {
    display: inline-block;
    width: 37px;
    height: 37px;
    background: url(../img/sprites.png);
}

IE7 does not support display:inline-block;

You might try changing that to float.

:checked

Also, IE7 has issues with attribute selectors.

So #euro:checked won't work.

But this might #euro[checked]. If it does, you could serve it to IE<9 with a conditional comment.

jQuery

I might just use some scripting, though. In that case, leave the css as is and add something this for the IE<9 (untested)

$('#euro:checked').next('label').css('background-position','1108px 898px');
Jason Gennaro
  • 34,535
  • 8
  • 65
  • 86
  • Yeah, I knew IE7 has issues with `display: inline-block`, but it's displaying as expected. If I'll found some output error I'll change it, thank you. I've tried `#euro[checked] + label` but nothing has happened `:-(` I'm giving a chance to Gerben's solution. Thank you for your answer anyway `:-)` – Ale A Sep 18 '11 at 14:18
  • i know this answer is old, but you can use a hack to get past `display:inline-block` in IE7. just add `*zoom:1;*display:inline;` to the CSS (i would use conditional tags), and it creates the exact behavior u want from `inline-block`. – PlantTheIdea Sep 03 '13 at 20:38