How to replace radio buttons with images? [duplicate]
Asked Answered
L

7

15

I would like to, instead of the standard radio button, use distinct images for each radio button. For the selected state I would like for a border to appear around the image.

I have tried making the images labels for the radio button and then hiding the button, but that seems to break the functionality for some reason.

I also have come across this article: http://ryanfait.com/resources/custom-checkboxes-and-radio-buttons/ which I could potentially somehow twist to my purposes.

Is there an easier/better way?

Lise answered 25/2, 2011 at 2:34 Comment(0)
J
21

jQuery

        $('input:radio').hide().each(function() {
            $(this).attr('data-radio-fx', this.name);
            var label = $("label[for=" + '"' + this.id + '"' + "]").text();
            $('<a ' + (label != '' ? 'title=" ' + label + ' "' : '' ) + ' data-radio-fx="'+this.name+'" class="radio-fx" href="#">'+
                '<span class="radio' + (this.checked ? ' radio-checked' : '') + '"></span></a>').insertAfter(this);
        });
        $('a.radio-fx').on('click', function(e) {
            e.preventDefault();
            var unique = $(this).attr('data-radio-fx');
            $("a[data-radio-fx='"+unique+"'] span").attr('class','radio');
            $(":radio[data-radio-fx='"+unique+"']").attr('checked',false);
            $(this).find('span').attr('class','radio-checked');
            $(this).prev('input:radio').attr('checked',true);
        }).on('keydown', function(e) {
            if ((e.keyCode ? e.keyCode : e.which) == 32) {
                $(this).trigger('click');
            }
        });
  • full code in demo source;
Judaic answered 25/2, 2011 at 2:55 Comment(15)
something like that, but that would play nice with prototype and scriptaculousLise
you don't need scriptaculous for do that, just prototype whould be fine, i think is not so difficult to rewrite my code in order to work with it.Judaic
I really appreciate the help, I will upvote/select this as answer as appropriate when I find time today to step through your solutionLise
Thanks. I just want to let others know that the demo source is a bit different (more complete), because it can be used with radio button groups.Frustrated
Seems like an accessibility nightmare. Also, wouldn't it be better to use prop rather than attr?Supine
@steveax: regarding accessibility, i'm still able to use tab + enter to set each radio and in case javascript is not available i'm still able to work with each radio; about prop against attr, yes you can feel free to use it depending on what version of jquery you are serving. PS: in the demo i have also replaced the use of div with span to be strict. And don't forget this is just a proof of concept.Judaic
The normal method of selecting a radio button (or checkbox) is with the spacebar, not enter (enter will submit the form). In addition, unlike a radio button with a properly associated label, there is nothing to tell a screenreader user what they are activating (be aware screen readers do not reliably read content in a title attribute.)Supine
@steveax: so add the title attribute and use keyup and keydown to detect the spacebar.Judaic
No, do not rely on the title attribute to convey essential information. Depending upon the screenreader and user settings, this may not be announced. It would be better to have content in the a link as this will be announced. That said, I think the entire notion of replacing radio buttons is dubious at best from usability and accessibility standpoints. It's very difficult to reliably support all users. This is getting a bit long, probably should move any further comments to chat.Supine
i have updated the demo! let's take a look!Judaic
Thanks for this code, it's brilliant! One question: Is there any way to have one of the checkbox (icon) pre-checked? It seems that checked="checked" does not work...Obaza
@user1464106: thanks for the hint, i have updated the code check it and let me know! ;)Judaic
Maybe I'm wrong here, but this doesn't seem to work from what I can tell. Shouldn't the checked="checked" attribute get removed if the user selects an option and then changes their mind and selects something different? The existing checked attribute seems to remain. This is true in my working copy and in the demo provided.Thurston
Again, I'm not sure if it is necessary - but if you need to remove the checked attribute you can add the following as the first line of the .on('click') function. - $('input:radio:checked').removeAttr('checked');Thurston
@norsewulf: thanks for advice, i have fixed the problem and also updated to latest jquery version...Judaic
B
33

Yes, there is! This is an example of the simple ways:

No need for javascript

CSS

.radio_item{
display: none !important;
}

.label_item {
opacity: 0.1;
}

.radio_item:checked + label {
opacity: 1;
}

HTML

<!--RADIO 1-->
<input type="radio" class="radio_item" value="" name="item" id="radio1">
<label class="label_item" for="radio1"> <img src="img_url_here"> </label>

<!--RADIO 2-->
<input type="radio" class="radio_item" value="" name="item" id="radio2">
<label class="label_item" for="radio2"> <img src="img_url_here"> </label>

FIDDLE

Brockbrocken answered 15/12, 2014 at 12:54 Comment(1)
This doesn't account for separate images for "checked" and "unchecked" states.Ricercar
J
21

jQuery

        $('input:radio').hide().each(function() {
            $(this).attr('data-radio-fx', this.name);
            var label = $("label[for=" + '"' + this.id + '"' + "]").text();
            $('<a ' + (label != '' ? 'title=" ' + label + ' "' : '' ) + ' data-radio-fx="'+this.name+'" class="radio-fx" href="#">'+
                '<span class="radio' + (this.checked ? ' radio-checked' : '') + '"></span></a>').insertAfter(this);
        });
        $('a.radio-fx').on('click', function(e) {
            e.preventDefault();
            var unique = $(this).attr('data-radio-fx');
            $("a[data-radio-fx='"+unique+"'] span").attr('class','radio');
            $(":radio[data-radio-fx='"+unique+"']").attr('checked',false);
            $(this).find('span').attr('class','radio-checked');
            $(this).prev('input:radio').attr('checked',true);
        }).on('keydown', function(e) {
            if ((e.keyCode ? e.keyCode : e.which) == 32) {
                $(this).trigger('click');
            }
        });
  • full code in demo source;
Judaic answered 25/2, 2011 at 2:55 Comment(15)
something like that, but that would play nice with prototype and scriptaculousLise
you don't need scriptaculous for do that, just prototype whould be fine, i think is not so difficult to rewrite my code in order to work with it.Judaic
I really appreciate the help, I will upvote/select this as answer as appropriate when I find time today to step through your solutionLise
Thanks. I just want to let others know that the demo source is a bit different (more complete), because it can be used with radio button groups.Frustrated
Seems like an accessibility nightmare. Also, wouldn't it be better to use prop rather than attr?Supine
@steveax: regarding accessibility, i'm still able to use tab + enter to set each radio and in case javascript is not available i'm still able to work with each radio; about prop against attr, yes you can feel free to use it depending on what version of jquery you are serving. PS: in the demo i have also replaced the use of div with span to be strict. And don't forget this is just a proof of concept.Judaic
The normal method of selecting a radio button (or checkbox) is with the spacebar, not enter (enter will submit the form). In addition, unlike a radio button with a properly associated label, there is nothing to tell a screenreader user what they are activating (be aware screen readers do not reliably read content in a title attribute.)Supine
@steveax: so add the title attribute and use keyup and keydown to detect the spacebar.Judaic
No, do not rely on the title attribute to convey essential information. Depending upon the screenreader and user settings, this may not be announced. It would be better to have content in the a link as this will be announced. That said, I think the entire notion of replacing radio buttons is dubious at best from usability and accessibility standpoints. It's very difficult to reliably support all users. This is getting a bit long, probably should move any further comments to chat.Supine
i have updated the demo! let's take a look!Judaic
Thanks for this code, it's brilliant! One question: Is there any way to have one of the checkbox (icon) pre-checked? It seems that checked="checked" does not work...Obaza
@user1464106: thanks for the hint, i have updated the code check it and let me know! ;)Judaic
Maybe I'm wrong here, but this doesn't seem to work from what I can tell. Shouldn't the checked="checked" attribute get removed if the user selects an option and then changes their mind and selects something different? The existing checked attribute seems to remain. This is true in my working copy and in the demo provided.Thurston
Again, I'm not sure if it is necessary - but if you need to remove the checked attribute you can add the following as the first line of the .on('click') function. - $('input:radio:checked').removeAttr('checked');Thurston
@norsewulf: thanks for advice, i have fixed the problem and also updated to latest jquery version...Judaic
C
3

I haven't looked into it, but this sounds promising: http://www.thecssninja.com/css/custom-inputs-using-css

Cockaigne answered 13/4, 2011 at 14:5 Comment(2)
+1 for pure-CSS solution. Lea Verou describes the same method in this presentation.Tourney
Just tried this cssninja one and it's by far the best solution I've seen. Main advantage is it doesn't conflict with other jquery radio button manipulation you do such as .prop('checked', true) like aSeptik's answer doesCounterclockwise
M
2

I had the same problem only a short while ago and found this jQuery solution which works perfectly and degrades nicely:

http://www.adamcoulombe.info/lab/jquery/select-box/

I used it to custom style select drop downs. It is very easy to implement. Replace the variable from $('.mySelectBoxClass') which targets the class to $('select') for example - and this would target all select elements on your page. The same rule would apply for radio buttons.

Melliemelliferous answered 25/2, 2011 at 5:10 Comment(0)
M
1

I don't think you'll find an easier way to do it than the link you added to your question. That is the only way I know of. I think you effectively answered your own question. Isn't there a badge for that or something?

Also, a similar question was answered here: Styling checkboxes, radio buttons and dropdowns

It contains a few more pre-built solutions that you can check out. Without more information on what you are trying to accomplish visually, I can't say if any of them will work for you.

Good luck!

Municipalize answered 25/2, 2011 at 2:54 Comment(0)
L
1

There is a bug with aSeptik's solution where if you click a checked radio button, it unchecks it. I corrected it by making the adjustment below.

$('a.radio-fx').on('click', function(e) {
        e.preventDefault();
        if($(this).prev('input:radio').is(':checked')) return;
        ...

so...

$('input:radio').hide().each(function() {
        $(this).attr('data-radio-fx', this.name);
        var label = $("label[for=" + '"' + this.id + '"' + "]").text();
        $('<a ' + (label != '' ? 'title=" ' + label + ' "' : '' ) + ' data-radio-fx="'+this.name+'" class="radio-fx" href="#">'+
            '<span class="radio' + (this.checked ? ' radio-checked' : '') + '"></span></a>').insertAfter(this);
    });
    $('a.radio-fx').on('click', function(e) {
        e.preventDefault();
        if($(this).prev('input:radio').is(':checked')) return;
        var unique = $(this).attr('data-radio-fx');
        $("a[data-radio-fx='"+unique+"'] span").attr('class','radio');
        $(":radio[data-radio-fx='"+unique+"']").attr('checked',false);
        $(this).find('span').attr('class','radio-checked');
        $(this).prev('input:radio').attr('checked',true);
    }).on('keydown', function(e) {
        if ((e.keyCode ? e.keyCode : e.which) == 32) {
            $(this).trigger('click');
        }
    });

Thank you aSeptik for the great solution!

Logistics answered 18/12, 2014 at 18:49 Comment(0)
T
1

very simple solution that i found on the net.

http://jsbin.com/image-instead-of-radio-button/3/edit?html,css,output

Transience answered 1/7, 2015 at 20:21 Comment(1)
Thats quite nice! However, on StackOverflow it is frowned upon to just put a link answer (see this meta post). If you explain a bit of the solution in your post, or even better yet, use StackOverflows new embed snippet to include a working example, then you definitely have my upvote. (leave the link of course as attribution)Lise

© 2022 - 2024 — McMap. All rights reserved.