5

I have the following CSS:

.foo
{
    height:100px;
    overflow:hidden;
    -webkit-transition: height 200ms;
    -moz-transition: height 200ms;
    -o-transition: height 200ms;
    transition: height 200ms;
}

.foo.open
{
    height:auto;
}

When .foo has an auto height, it will be a height of ~550px depending on the content.

I add the class open using jQuery, and I would expect to see the height change from 100px to ~550px in 200ms using CSS3 transitions.

However what exactly happens is that the height changes from 100px to 0px, then jumps to ~550px.

-- See Live Demo --

If I instead change .open to height:550px then this works fine, however the content length will vary and therefore I need to set the height to auto, and not a fixed pixel height.

Why is the div closing instead of sliding to ~550px, and how can I resolve this animation issue?

Curtis
  • 101,612
  • 66
  • 270
  • 352
  • possible duplicate of [CSS transition height: 0; to height: auto;](http://stackoverflow.com/questions/3508605/css-transition-height-0-to-height-auto) – Hashem Qolami Oct 24 '14 at 22:40

4 Answers4

9

I don't think you can transition to height: auto; with css transitions. A workaround, which isn't perfect is to transition max-height instead and set it to something greater then it will ever get. Depending on what value you set it to will have a effect on the transition speed, but I've set it to max-height: 1000px; for the sake of simplicity.

Here's a demo to show you what I mean.

Code from demo:

.foo
{
    max-height:100px;
    overflow:hidden;
    -webkit-transition: max-height 200ms;
    -moz-transition: max-height 200ms;
    -o-transition: max-height 200ms;
    transition: max-height 200ms;
}

.foo.open
{
    max-height:1000px;
}

It's not an elegant solution, but I hope it helps.

Christofer Vilander
  • 17,232
  • 6
  • 31
  • 26
  • Thanks for your response, this isn't perfect as the `min-height` needs to always be something similar to what the auto height would be. Otherwise the transition speed will differ. But this is still better than my solution. Do you have any reference as to why we can't go from fixed height to auto with transition? – Curtis Apr 10 '13 at 12:25
  • No, not really, but googling the issue I found this blog post which has a short explanation - http://blog.alexmaccaw.com/css-transitions – Christofer Vilander Apr 10 '13 at 15:28
1

This isn't the most elegant solution, but it gets around the auto height issue.

On click of the button, calculate the height the div will be with auto height by doing:

var openHeight = $foo.addClass("heightauto").height();

Then remove this class straight afterwards, and apply a height to the div of openHeight:

$foo.removeClass("heightauto");
$foo.height(openHeight);

The heightauto class also needs to override the CSS3 transitions so that the height is changed instantly:

.foo.heightauto
{
    height:auto;
    -webkit-transition:0;
    -moz-transition:0;
    -o-transition:0;
    transition:0;
}

See Live Demo: http://jsfiddle.net/AbPEx/4/

This is still hacky though, so if there is a more elegant solution then I'm open to suggestions

Curtis
  • 101,612
  • 66
  • 270
  • 352
1

It is not possible to use transitions with height:auto. The trick with max-height is a pretty good solution but has some inconvenience, especially a weird delay if max-height is much higher than the real height.

Here is the trick I use : http://jsfiddle.net/g56jwux4/2/ Basically it is two imbricated DIVs translating in opposite directions. Take a look a the code at jsfiddle because my english is not good enough to explain it clearly.

HTML part:

<body>
  <p>Technicaly this dropdown menu looks like a simple height transition.</p>
  <p>But this pure css code also works this a variable number of choices in menu, working around the "height:auto" not taken into account by css transitions.</p>
    <input type="checkbox" id="menuOpen"></input>
    <label id="bouton" for="menuOpen"><span>Click on me !</span>
        <div id="menu">
            <div id="masque">
                <div class="choix" id="choix1">Choix 1</div>
                <div class="choix" id="choix2">Choix 2</div>
                <div class="choix" id="choix3">Choix 3 tr&egrave;s tr&egrave;s long pour voir la taille finale du menu</div>
                <div class="choix" id="choix4">Choix 4</div>
                <div class="choix" id="choix5">Choix 5</div>
                <div class="choix" id="choix6">Choix 6</div>
            </div>
        </div>
    </label>
</body>

CSS Part :

body {
    font-family: sans-serif;
}
#menuOpen {
    display: none;
}
#bouton {
    position: absolute;
    left: 100px;
    top: 100px;
    width: 200px;
    height: 30px;
    background-color: lightgray;
    cursor: pointer;
}
#bouton > span {
    color: black;
    padding: 6px;
    line-height: 30px;
}
#menu {
    position: absolute;
    top: 100%;
    overflow: hidden;
    min-width: 100%;
    transition: transform 0.3s linear 0s, visibility 0.3s linear 0s;
    transform: translateY(-100%);
    visibility: hidden;
    color: white;
}
#menuOpen:checked + #bouton > #menu  {
    transform: translateY(0%);
    visibility: visible;
    transition: transform 0.3s linear 0s, visibility 0s linear 0s;
}
#menuOpen:checked + #bouton > #menu > #masque {
    transform: translateY(0%);
}
#masque {
    position: relative;
    background-color: gray;
    transform: translateY(100%);
    transition: transform 0.3s linear 0s;
}
.choix {
    white-space: nowrap;
    padding: 3px 6px;
}
.choix:hover {
    background-color: darkgray; 
}
Joël Hecht
  • 1,766
  • 1
  • 17
  • 18
0

There is a small bug in there, I already fix it. by adding min-height: 100px;

.foo {

min-height: 100px;
height: 100px;
...

}

There you won't see it go back to 0px.

Thaichor Seng
  • 105
  • 10
  • 1
    Thanks for your response, but this prevents the transition animation: http://jsfiddle.net/AbPEx/2/ – Curtis Apr 10 '13 at 09:51