Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate parent height auto when children height is modified

I have a parent div with height set to auto.

Now whenever I fade something in that's a child of that div, the height just jumps to the new height. I want this to be a smooth transition.

The height is supposed to transition before any children are being displayed, and also transition after any children are being removed (display: none;).

I know this is possible when you know the predefined heights, but I have no idea how I can achieve this with the height being set to auto.

JSFiddle Demo

like image 719
Kid Diamond Avatar asked Nov 02 '22 04:11

Kid Diamond


2 Answers

You could load new content with display: none and slideDown() it in and then fadeIn with animated opacity. Before you remove it you just fade out and slideUp()

I think this is what you wanted: jsFiddle

$(function() {
    $("#foo").click(function() {
        if($("#bar").is(":visible")) {
            $("#bar").animate({"opacity": 0}, function() {
                $(this).slideUp();
            });
        }
        else {
            $("#bar").css({
                "display": "none",
                "opacity": 0,
                /* The next two rows are just to get differing content */
                "height": 200 * Math.random() + 50,
                "background": "rgb(" + Math.round(255 * Math.random()) + "," + Math.round(255 * Math.random()) + "," + Math.round(255 * Math.random()) + ")"
            });
            $("#bar").slideDown(function() {
                $(this).animate({"opacity": 1});
            });
        }
    });
});

Try this also: jsFiddle. Click "Click me" to add new divs. Click on a new div to remove it.

$(function() {
    $("#foo").click(function() {
        var newCont = $("<div>").css({
            "display": "none",
            "opacity": 0,
            "height": 200 * Math.random(),
            "background": "rgb(" + Math.round(255 * Math.random()) + "," + Math.round(255 * Math.random()) + "," + Math.round(255 * Math.random()) + ")"
        });
        $(this).append(newCont);
        newCont.slideDown(function() {
            $(this).animate({"opacity": 1});
        });
        newCont.click(function(e) {
            $(this).animate({"opacity": 0}, function() {
                $(this).slideUp(function() {
                    $(this).remove();
                });
            });
            return false;
        });
    });
});
like image 92
Mathias Avatar answered Nov 14 '22 05:11

Mathias


The approach I took was to see if .bar was visible, and if so fade it out, the animate the height of #foo back to where it started, or animating it to the height of .bar + #foo otherwise, using callbacks in both cases to get the effect that you were looking for.

Code:

$(function() {
    var start_height = $('#foo').outerHeight();
    $("#foo").click(function() {
        $bar = $('.bar');
        $foo = $(this);
        if($bar.is(':visible')) {
            $bar.fadeToggle('slow', function() {
                $foo.animate({height: start_height});
            });
        } else {
            $foo.animate({height: ($bar.outerHeight()+start_height)+'px'}, 'slow', function() {
                $bar.fadeToggle();
            });
        }
    });
});

Fiddle.

EDIT:

Added .stop() to prevent unexpected behavior when double clicked.

Updated Fiddle.

like image 36
Samsquanch Avatar answered Nov 14 '22 05:11

Samsquanch