I have made a frig which solves this, by applying display: table-row- group instead of display: block for TBODY elements. There's a slight "bounce" when unhiding (Firefox 3.0.13) - seems the height goes a few pixels to far - but otherwise it seems OK.
I doubt this hard-coded logic is the right way to handle it, but on the other hand, I don't understand why jquery works in the way it does right now. (1) Why apply an explicit "display: block" style instead of just removing the display style? (2) The element's original display style is captured in the animate() function already: // Store display property opt.display = jQuery.css(this, "display"); and this indeed gives 'table-row-group' for a TBODY element - but it isn't used when animating, since the update() function forces it to be "block" anyway. It's reset at the end of the animation though. (3) After hiding something you get display: none, so in the above code opt.display is set to "none" when subsequently unhiding, which is then forced to be "block" later on. (See "Reset the display" in function step()) Anyway, here's my patch. I'd appreciate any suggestions as to how to solve this problem better. Regards, Brian. --- jquery-1.3.2.js.orig 2009-07-05 17:02:00.000000000 +0100 +++ jquery-1.3.2.js 2009-09-03 09:02:21.000000000 +0100 @@ -615,6 +615,10 @@ defaultView = document.defaultView || {}, toString = Object.prototype.toString; +var tagBlockStyle = { + TBODY: 'table-row-group' + }; + jQuery.extend({ noConflict: function( deep ) { window.$ = _$; @@ -731,6 +735,10 @@ } }, + blockDisplayStyle: function( elem ) { + return tagBlockStyle[ elem.tagName ] || "block"; + }, + // A method for quickly swapping in/out CSS properties to get correct calculations swap: function( elem, options, callback ) { var old = {}; @@ -3801,7 +3809,7 @@ display = elem.css("display"); if ( display === "none" ) - display = "block"; + display = jQuery.blockDisplayStyle( elem ); elem.remove(); @@ -4021,7 +4029,7 @@ // Set display property to block for height/width animations if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style ) - this.elem.style.display = "block"; + this.elem.style.display = jQuery.blockDisplayStyle( this.elem ); }, // Get the current size @@ -4114,7 +4122,7 @@ // Reset the display this.elem.style.display = this.options.display; if ( jQuery.css(this.elem, "display") == "none" ) - this.elem.style.display = "block"; + this.elem.style.display = jQuery.blockDisplayStyle ( this.elem ); } // Hide the element if the "hide" operation was done