Animating max-height with CSS transitions

CssCss TransitionsCss Animations

Css Problem Overview


I want to create an expand/collapse animation that's powered only by classnames (javascript is used to toggle the classnames).

I'm giving one class max-height: 4em; overflow: hidden;

and the other max-height: 255em; (I also tried the value none, which didn't animate at all)

this to animate: transition: max-height 0.50s ease-in-out;

I used CSS transitions to switch between them, but the browser seems to be animating all those extra em's, so it creates a delay in the collapse effect.

Is there a way of doing it (in the same spirit - with css classnames) that doesn't have that side-effect (I can put a lower pixel count, but that obviously has drawbacks, since it might cut off legit text - that's the reason for the big value, so it doesn't cut off legit long text, only ridiculously long ones)

See the jsFiddle - http://jsfiddle.net/wCzHV/1/ (click on the text container)

Css Solutions


Solution 1 - Css

Fix delay solution:

Put cubic-bezier(0, 1, 0, 1) transition function for element.

scss

.text {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.5s cubic-bezier(0, 1, 0, 1);

  &.full {
    max-height: 1000px;
    transition: max-height 1s ease-in-out;
  }
}

css

.text {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.5s cubic-bezier(0, 1, 0, 1);
}

.text.full {
  max-height: 1000px;
  transition: max-height 1s ease-in-out;
}

Solution 2 - Css

This is an old question but I just worked out a way to do it and wanted to stick it somewhere so I know where to find it should I need it again :o)

So I needed an accordion with clickable "sectionHeading" divs that reveal/hide corresponding "sectionContent" divs. The section content divs have variable heights, which creates a problem as you can't animate height to 100%. I've seen other answers suggesting animating max-height instead but this means sometimes you get delays when the max-height you use is larger than the actual height.

The idea is to use jQuery on load to find and explicitly set the heights of the "sectionContent" divs. Then add a css class 'noHeight' to each a click handler to toggle it:

$(document).ready(function() {
    $('.sectionContent').each(function() {
        var h = $(this).height();
        $(this).height(h).addClass('noHeight');
    });
    $('.sectionHeader').click(function() {
        $(this).next('.sectionContent').toggleClass('noHeight');
    });
});

For completeness, the relevant css classes:

.sectionContent {
    overflow: hidden;
    -webkit-transition: all 0.3s ease-in;
    -moz-transition: all 0.3s ease-in;
    -o-transition: all 0.3s ease-in;
    transition: all 0.3s ease-in;
}
.noHeight {
        height: 0px !important;
}

Now the height transitions work without any delays.

Solution 3 - Css

In case anyone is reading this, I have not found a solution and went with an expand-only effect (which was achieved by moving the transition style to the expanded class definition)

Solution 4 - Css

The solution is actually quite simple. Make a child div, that has the content. The parent div will be the one that expands collapses.

On load the parent div will have a max-height. when toggling, you can check the child height by writing document.querySelector('.expand-collapse-inner').clientHeight; and set the maxheight with javascript.

In your CSS, you will have this

.parent {
transition: max-height 250ms;
}

Solution 5 - Css

Use display:flex. This will work:

.parent > div {
  display: flex;
  flex-direction: column;
  height: 0px;
  max-height: 0px;
  opacity: 0;
  overflow: hidden;
  transition: all 0.3s;
}

.parent > div.active {
  opacity: 1; 
  height: 100%;
  max-height: none; /* important for animation */
}

Solution 6 - Css

You can accomplish this just fine using jQuery Transit:

$(function () {
    $(".paragraph").click(function () {
        var expanded = $(this).is(".expanded");
        if (expanded) 
        {
            $(this).transition({ 'max-height': '4em', overflow: 'hidden' }, 500, 'in', function () {$(this).removeClass("expanded"); });
        } 
        else 
        {
            $(this).transition({ 'max-height': $(this).get(0).scrollHeight, overflow: ''}, 500, 'out', function () { $(this).addClass("expanded"); });
        }
    });
});

You can definitely tidy it up a bit to your liking, but that should do what you want.

JS Fiddle Demo

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMadd0gView Question on Stackoverflow
Solution 1 - Cssegor.xyzView Answer on Stackoverflow
Solution 2 - CssWill JenkinsView Answer on Stackoverflow
Solution 3 - CssMadd0gView Answer on Stackoverflow
Solution 4 - CssJohansrkView Answer on Stackoverflow
Solution 5 - CssLukasz ZdunekView Answer on Stackoverflow
Solution 6 - CssGaffView Answer on Stackoverflow