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?

Ari
  • 4,643
  • 5
  • 36
  • 52
Zach Lysobey
  • 14,959
  • 20
  • 95
  • 149

7 Answers7

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

Ari
  • 4,643
  • 5
  • 36
  • 52
22

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;
Luca Filosofi
  • 30,905
  • 9
  • 70
  • 77
  • something like that, but that would play nice with prototype and scriptaculous – Zach Lysobey Feb 25 '11 at 03:33
  • 1
    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. – Luca Filosofi Feb 25 '11 at 03:52
  • I really appreciate the help, I will upvote/select this as answer as appropriate when I find time today to step through your solution – Zach Lysobey Feb 25 '11 at 15:15
  • 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. – Petri Tuononen Jul 31 '12 at 19:49
  • Seems like an accessibility nightmare. Also, wouldn't it be better to [use `prop`](http://stackoverflow.com/questions/5874652/prop-vs-attr) rather than `attr`? – steveax Sep 18 '12 at 02:55
  • @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. – Luca Filosofi Sep 18 '12 at 09:35
  • 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.) – steveax Sep 18 '12 at 17:08
  • @steveax: so add the title attribute and use keyup and keydown to detect the spacebar. – Luca Filosofi Sep 18 '12 at 18:01
  • 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. – steveax Sep 18 '12 at 18:17
  • i have updated the demo! let's take a look! – Luca Filosofi Sep 18 '12 at 18:33
  • 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... – Oh_Franck Feb 15 '13 at 15:16
  • @user1464106: thanks for the hint, i have updated the code check it and let me know! ;) – Luca Filosofi Feb 15 '13 at 17:07
  • 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. – norsewulf Jun 03 '14 at 23:44
  • 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');` – norsewulf Jun 03 '14 at 23:53
  • @norsewulf: thanks for advice, i have fixed the problem and also updated to latest jquery version... – Luca Filosofi Jun 04 '14 at 11:35
3

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

  • 1
    +1 for pure-CSS solution. Lea Verou describes the same method [in this presentation](http://lea.verou.me/css3-secrets/#custom-form-controls). – GeReV Feb 15 '13 at 17:15
  • 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 does – BaronVonKaneHoffen Jul 11 '13 at 00:13
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.

Dan
  • 10,171
  • 7
  • 38
  • 31
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!

lbbrooks
  • 11
  • 1
1

very simple solution that i found on the net.

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

eliprodigy
  • 600
  • 6
  • 8
  • Thats quite nice! However, on StackOverflow it is frowned upon to just put a link answer [(*see this meta post*)](http://meta.stackoverflow.com/questions/251006/flagging-link-only-answers). 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) – Zach Lysobey Jul 01 '15 at 22:22
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!

Community
  • 1
  • 1
Dubmun
  • 478
  • 2
  • 10