IE - hidden radio button not checked when the corresponding label is clicked
Asked Answered
A

9

37

I just noticed a strange behaviour in IE7.

I have radio buttons with associated labels as follows:

<input type="radio" name="filter" id="filter_1" value="Activities" checked="checked" />
<label for="filter_1">Activities</label>

<input type="radio" name="filter" id="filter_2" value="Services" />
<label for="filter_2">Services</label>

The radio button is hidden via css with display:none or visibility: hidden (don't ask)

The problem is - when I click the label in IE7 (haven't looked at other IE versions yet) the associated radio button is not actually checked. I confirmed this with jquery - the label click event is fired, but the radio button click event is not. A form post also confirms that the checked radio button does not change.

This works correctly in firefox, and also works correctly if I remove the CSS that hides the radio buttons.

Is this an IE bug or am I missing something?

Alcides answered 10/8, 2009 at 0:37 Comment(0)
Q
43

It probably is to do with the display: none - you may also find that hidden elements don't get their values submitted with the rest of the form. If you have control over it, you may want to try positioning the elements off screen rather then hiding them.

Quadrisect answered 10/8, 2009 at 1:24 Comment(4)
+1 Yes, that will work. I'm more curious if this is a known bug in IE.Alcides
I don't think it's a known bug, so much as behaviour which is not clearly defined in the spec. Looking at the MSDN article which is linked to from the post I linked to above, it seems that this behaviour is entirely intentional on the part of IE. If something is display:none then it's effectively not part of the document. MS have chosen to therefore ignore these elements, Mozilla have chosen not to, it's not like there's a clearly right or wrong way to do it.Quadrisect
It's not very cool when a designer's CSS can break the data coming into a developer's form handler by failing to pass along a piece of data. This behavior smells wrong. Thanks for the workaround!Crowberry
Indeed after setting position to absolute and top:-9999px it started to work. tyDarcee
H
19

This is a wiki answer to bring together all the different answers and options.

Option 1: Move the element off-screen as opposed to hiding it completely

position: absolute;
top: -50px;
left: -50px;

Option 2: Use a bit of JavaScript to set the radio button to checked when the label is clicked

$("label").click(function(e){
    e.preventDefault(); 
    $("#"+$(this).attr("for")).click().change(); 
});

Option 3: Set the element's width and/or opacity to zero

width: 0;
/* and/or */
-moz-opacity:0;
filter:alpha(opacity:0);
opacity:0;
outline:none; /* this prevents IE8 from having the line around it even though it's invisible */

Option 4: Use another browser :)

Basically, the spec for these things doesn't specifically state what behavior to use, but IE generally takes the stance that if it can't be seen, then it doesn't work. "Seen" and "work" can mean different things, but in this case it means that when display:none is set, the label doesn't activate the radio button, which leads to the usual workarounds necessary for so many things in IE.

Homo answered 10/8, 2009 at 0:37 Comment(3)
if you do Option 1 clicking on labels will result in an unwanted page scroll in FF, IE and Opera because the browser will try to focus on the inputBackdate
@Dan not sure, but a return false onclick might fix that behavior.Darkling
Added outline:none; to option 3. Probably the best option also. outline none prevents the jagged line around the radio button when clicked in IE8Chryso
K
5

This works for me

width: 0px;

Tested in IE7 and IE8. Pure CSS no javascript.

Kirkman answered 30/3, 2012 at 0:59 Comment(0)
E
4

This issue exists in IE6, 7, 8, and even the current 9 beta. As a fix, positioning the radio button offscreen is a good idea.

Here's an alternative that doesn't have to involve the designer or the css: Hide the button normally, and make whatever function handles the click event for the button also handle the click event for the label.

Embolectomy answered 27/12, 2010 at 19:8 Comment(3)
$("label").click(function(e){ e.preventDefault(); $("#"+$(this).attr("for")).click().change(); });Curricle
Lane, that's a really cool solution. I'm adding it as an answer so people don't overlook it like I almost did :)Karyolysis
Note: this issue also affects IE 10 and IE 11Drubbing
K
4
$("label").click(function(e){
    e.preventDefault(); 
    $("#"+$(this).attr("for")).click().change(); 
});

Thanks Lane for this. I'm adding it as an answer here so people don't overlook your comment.

Karyolysis answered 26/9, 2011 at 14:37 Comment(1)
I scoped this function to only run on IE with the following if statement wrapper: if (navigator.userAgent.indexOf('MSIE')!==-1 || navigator.appVersion.indexOf('Trident/') > 0) { /* insert code snippet here */ }Drubbing
I
1

Replace

style="display:none;"

with

style="-moz-opacity:0;filter:alpha(opacity:0);opacity:0;"
Instable answered 11/7, 2011 at 19:21 Comment(0)
J
1

You can try this for IE7,8:

input{
    position: absolute;
    z-index: -1;
}

instead of

input{
    display: none;
}
Jonson answered 8/12, 2011 at 8:32 Comment(0)
T
1

There is some nice compilation of Your propositions:

input {
-moz-opacity:0;
filter:alpha(opacity:0);
opacity:0;
position: absolute;
}

instead of:

display: none;
Tuition answered 1/6, 2012 at 13:20 Comment(0)
D
0

I was using jQuery hide() function, so it wasn't easy to change the way an element is hide without writing a more complex code. I found this idea: I use class to store the checked attribute and set this attribute back again just before the submit.

if ($.browser.msie && $.browser.version == 7.0) {
$('input[type=radio]').click(function() {
    $('input[name="'+$(this).attr("name")+'"]').each(function(){
        if ($(this).attr("checked")){
            $(this).addClass("checked");
        }else{
            $(this).removeClass("checked");
        }
    });
});
$('form').submit(function(){
    $('input.checked').each(function(){
        $(this).attr("checked","true");
    });
});
}

It works like a charm in my case.

Distracted answered 22/6, 2012 at 19:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.