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
Solution 4
A better solution would not rely on JS to set the height of your element. The following is a solution that animates a fixed height element to full ("auto") height:
var $selector = $('div');
$selector
.data('oHeight',$selector.height())
.css('height','auto')
.data('nHeight',$selector.height())
.height($selector.data('oHeight'))
.animate({height: $selector.data('nHeight')},400);
https://gist.github.com/2023150
Solution 5
this is working and it is simplier then solutions before:
CSS:
#container{
height:143px;
}
.max{
height: auto;
min-height: 143px;
}
JS:
$(document).ready(function() {
$("#container").click(function() {
if($(this).hasClass("max")) {
$(this).removeClass("max");
} else {
$(this).addClass("max");
}
})
});
Note: This solution requires jQuery UI
Related videos on Youtube
Daniel
Updated on September 23, 2020Comments
-
Daniel over 3 years
I want to animate a
<div>
from200px
toauto
height. I can’t seem to make it work though. Does anyone know how?Here’s the code:
$("div:first").click(function(){ $("#first").animate({ height: "auto" }, 1000 ); });
-
kleinfreund almost 10 yearsYou should mark the best answer as accepted.
-
Ian Mackinnon about 9 yearspossible duplicate of How can I Animate an Element to its natural height using jQuery
-
Madara's Ghost about 9 years@IanMackinnon this question certainly has better answers. I've closed that question as a duplicate of this.
-
-
Katya Appazova about 13 yearsthis is not gonna work your var height is just accessible inside the ready function.
-
David Tang about 13 years@Daniel, where is your JS code? Post that bit, and also parts of the HTML that show the elements you refer to.
-
EMMERICH about 13 yearsAh. Well, it seems you've discovered the solution. For safety, I'd still use
$(this)
inside your click handler. -
Prakash about 13 yearsdefine the height before the ready function, and use only height than var height.. this way it may work daniel
-
jinyong lee over 11 years
animate({height: 'auto'})
doesn't have any effect. At least, not with jQuery 1.6.4. -
user56reinstatemonica8 over 11 yearsIt should be mentioned that this requires the Jquery UI plugin, while the original question was about jquery alone. But if you're using Jquery UI, it works.
-
rg89 over 11 yearsThis works, but I added a callback that restores the auto-grow behavior to the element
.animated({height: autoHeight}, 1000, function(){ el.height('auto'); });
-
Jaap over 11 yearsThis doesn't solve the height:auto function since slideUp will completely collapse the div.
-
Jaap over 11 yearsThis oneliner is not easy to understand, maybe writing several lines would help others a little better.
-
Antoine Hedgecock over 10 yearsyou could also use $(this).toggleClass('max', 250); instead of using the if statement
-
Jonathan Tonge over 10 yearsBecareful about setting fixed heights on responsive designs. It turns into a mess if the user resizes the screen. Best to set height to 'auto' once the animation is complete.
-
Ricky Sahu almost 10 yearsThis is the best solution because the auto height may change if the user adjusts the window size. See the following: //animates the height of the filters function toggleSlider(){ if ($('#filters').height() != 0) { $('#filters').animate({height:'0'}); } else{ var $selector = $('#filters'); $selector .data('oHeight',$selector.height()) .css('height','auto') .data('nHeight',$selector.height()) .height($selector.data('oHeight')) .animate({height: $selector.data('nHeight')},400); }; console.log('agg'); }
-
Steffi almost 10 yearsyou can replace :
.appendTo("body")
by.appendTo(el.parent())
-
PHearst over 9 yearsIf you don't start with a fixed height of '200px' like the OP, you can set the element to '100%' with CSS and it works as well.
-
Dingredient over 9 yearsThis has the potential to cause FOUC. The user might see the element jump to full height for a split second before animating.
-
Sven over 9 yearsAmazing! According to developer.mozilla.org/en-US/docs/Web/API/Element.scrollHeight it's even supported in IE8, compared to
clientHeight
, which seems to be unsupported: developer.mozilla.org/en-US/docs/Web/API/Element.clientHeight -
Timothy Groote about 9 yearsEssentially the same as Hettler's one liner, but easier to understand.
-
Jack James about 9 yearsthis doesn't seem to take margins into account
-
Liquinaut almost 9 yearsMargin is by definition of the box model not part of the height of an object. You could always add the margin yourself, though.
-
bytesized almost 9 yearsI was having problems with the accepted answer. Sometimes (but not always), it would get the same value for the current height and the auto height. This answer works perfectly for me. I am surprised I have never seen the
scrollHeight
property before. -
Einius almost 9 yearsThis should be the accepted answer as it works best without any flickering and really does the job well
-
FiftyStars over 8 yearstemporary switching to auto height is really visible for a couple of frames
-
Chris Williams over 8 yearsI also think this is the best solution. I would add to it a callback function to set height to auto for more responsiveness.
$('#first').animate({ height: $('#first').get(0).scrollHeight }, 1000, function() { $(this).height('auto'); });
-
nils over 8 yearsWow, this is super elegant. It also works with
scrollWidth
for width animations. -
tomarrell over 8 yearsFantastic solution. Deserves the accept. Also works when the window is resized whereas the other doesn't unless you write a function to modify the initial heights and redo all the calculations.
-
ntgCleaner about 8 yearsWorks to make the div open up, but does not animate over 400ms. Maybe I have something else set differently, but it just opens in a blink.
-
JacobEvelyn about 8 yearsYou can prevent the FOUC ("flash of unstyled content") by initially giving the element
opacity: 0; position: absolute;
while measuring it and removing those once you're done. -
Stan George almost 8 yearsIf you don't want to use that function just do something like: var clone = element.clone() clone.appendTo('body') clone.css('height', 'auto') var itemHeight = clone.outerHeight(); clone.remove() now you have your item's height in itemHeight variable, so you can use it for more than just animations.
-
jsruok almost 7 yearsWorks but this sets
height
to a fixed value (e.g. 122px). My element changed height after a while, so I had to replace the duration argument (400) with options{duration: 400, complete: function() {$selector.css('height', 'auto');}}
-
bowl0stu almost 7 yearswhy are you including a second value with the
.addClass
and.removeClass
?