Monday, August 17, 2009

jQuery slideUp flickers in Internet Explorer quirks mode

I had this expand/collapse div on which I was using slideToggle to make it look good. However, in quirks mode (HTML Transitional 4.01 DocType) and on IE7 the div would briefly pop up after collapsing, showing an annoying flicker. It seems that Internet Explorer has a problem rendering stuff with height 0px.

The solution I found: replace target.slideUp(speed,callBack) with
var h = target.height();
var cssHeight=target.css('height');
target.animate(
{ height: '1px' }, speed, function() {
target.hide();
target.height(h);
target.css('height',cssHeight);
callBack();
}
);
I have also created a jQuery ticket to suggest they use the same method in the library itself.

Update 1 Sep 2009: I have added the cssHeight variable to restore the actual css height settings, not just the height.

Update 21 May 2011: commenter Mads shared a more elegant solution in the form of this script:
(function(){
// Define overriding method.
jQuery.fx.prototype.hide = function(){

// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
this.options.hide = true;

// Begin the animation
this.custom(this.cur(), 1);
}
})();
used anywhere after the jQuery include. Thanks, man!

16 comments:

Anonymous said...

Thank you!
The IE bug is still not resolved in jQuery 1.3.2. All the "IE peek-a-boo" hacks didn't work for me. This has, and it is by far a much more elegant solution.

Moose said...

Hi,

I am running jQuery JavaScript Library v1.3.2 but cannot find the line you reference to fix the IE flicker bug:

target.slideUp(speed,callBack)

Am I looking at the correct file? I'd love to fix this bug.

Thanks so much.

Siderite said...

slideUp is the method you use in your code and that results in problems on Internet Explorer. What I am suggesting is using the piece of code in the post instead of slideUp when IE is used.

I have looked into the jQuery animation engine to see if I can fix slideUp directly, but it was too complicated for my alloted time.

Anonymous said...

Many thanks for your solution, it took me on the right path. But sadly your code isn't working well on my side. If i want to reshow the hidden element (slideDown()) it behaves even worse compared to the flickering on hiding / slideUp.

So - what did the trick:
I just changed in the original jQuery script the function for minimizing the element to the height 1 instead of 0.

Here is the code:


// Simple 'hide' function
hide: function(){
// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
this.options.hide = true;

// Begin the animation
this.custom(this.cur(), 1);
},


I just change 0 to 1...

Let me know if it works for you.

Hiswe said...

Thanks for you're post !!
It really helps me :)

Moose said...

Changing 0 to 1 in this.custom(this.cur(), 1); worked for me!

Thanks SO much. This was bugging the crap out of me!!!

Ofer said...

John Resig just changed that ticket status to "wontfix" due to the fact that setting the page to Strict Mode fixes the issue.

Siderite said...

Well, wouldn't it be nice if changing the doctype for all the pages in a large project would fix anything, rather than a single line of code in jQuery?

For me, that was not an option (although I have tried to convince the stakeholders) so I am working with my own patched jQuery.

Moose said...

Yeah, I tried changing the doctype, too. It fixed the issue but it also hosed the rest of the site's layout.

Our site is an ancient piece of crap, probably with the wrong doctype anyway, but until we re-build it, this was a great fix.

Anonymous said...

Thanks buddy. It really saved my day.

Anonymous said...

Thanks buddy for saving my 2 days effort
my effort was about to scrapped just because of this annoying flickering

I used your slideUp and made similar slideDown here is slideDown function :D

var h = target.height();
var cssHeight = target.css('height');
target.height('1px');
target.css('height', '1px');
target.show();
target.animate({ height: h }, 500, function() {
target.height(h);
target.css('height', cssHeight);
}
);

Tony Lea said...

Thanks, This issue should be resolved with the latest version of jQuery. Please feel free to check out the following resource for a beginner rundown of the jquery slideup and slidedown functionality: http://www.tonylea.com/2010/jquery-slideup-and-slidedown/

Anonymous said...

The issue still exists in jQuery v 1.5.3 and v1.6.1.

Mads said...

If you don't want to use a custom version of jQuery, you could always override the core method like this:

(function(){
// Define overriding method.
jQuery.fx.prototype.hide = function(){

// Remember where we started, so that we can go back to it later
this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
this.options.hide = true;

// Begin the animation
this.custom(this.cur(), 1);
}
})();

Just paste the above script, anywhere after your jQuery include, and you'll be fine.

This is not a perfect solution, as you have to make sure the hide method dosn't change, upon update of jQuery source. However the method hasn't changed in 2 years or more, so chances are that it won't anytime soon.

Anonymous said...

Thabks...this works for me too!! :)

Anonymous said...

Thanks! Good job!