Animate element to auto height with jQuery
Solution 1:
-
Save the current height:
var curHeight = $('#first').height();
-
Temporarily switch the height to auto:
$('#first').css('height', 'auto');
-
Get the auto height:
var autoHeight = $('#first').height();
-
Switch back to
curHeight
and animate toautoHeight
:$('#first').height(curHeight).animate({height: autoHeight}, 1000);
And together:
var el = $('#first'),
curHeight = el.height(),
autoHeight = el.css('height', 'auto').height();
el.height(curHeight).animate({height: autoHeight}, 1000);
Solution 2:
IMO this is the cleanest and easiest solution:
$("#first").animate({height: $("#first").get(0).scrollHeight}, 1000 );
Explanation: The DOM already knows from its initial rendering what size the expanded div will have when set to auto height. This property is stored in the DOM node as scrollHeight
. We just have to fetch the DOM Element from the jQuery Element by calling get(0)
and then we can access the property.
Adding a callback function to set the height to auto allows for greater responsiveness once the animation is complete (credit chris-williams):
$('#first').animate({
height: $('#first').get(0).scrollHeight
}, 1000, function(){
$(this).height('auto');
});
Solution 3:
This is basically the same approach as the answer by Box9 but I wrapped it in a nice jquery plugin that takes the same arguments as a regular animate, for when you need to have more animated parameters and get tired of repeating the same code over and over:
;(function($)
{
$.fn.animateToAutoHeight = function(){
var curHeight = this.css('height'),
height = this.css('height','auto').height(),
duration = 200,
easing = 'swing',
callback = $.noop,
parameters = { height: height };
this.css('height', curHeight);
for (var i in arguments) {
switch (typeof arguments[i]) {
case 'object':
parameters = arguments[i];
parameters.height = height;
break;
case 'string':
if (arguments[i] == 'slow' || arguments[i] == 'fast') duration = arguments[i];
else easing = arguments[i];
break;
case 'number': duration = arguments[i]; break;
case 'function': callback = arguments[i]; break;
}
}
this.animate(parameters, duration, easing, function() {
$(this).css('height', 'auto');
callback.call(this, arguments);
});
return this;
}
})(jQuery);
edit: chainable and cleaner now