Last Updated: November 12, 2017
·
13.36K
· robsonsobral

CSS transition with auto width or height

To set transition on the dimensions of an element which doesn't have its dimensions specifically set is a problem. From MDN:

Also the auto value is often a very complex case. The specification asks not to animate from and to such a value. Some user agents, like those based on Gecko, implement this requirement and others, like those based on WebKit, are less strict. Using animations with auto may lead to unpredictable results, depending of the browser and its version, and should be avoided.

But sometimes you just don't know the dimension of the element. They are defined by its content.

The trick is that we can, most of times, guess a value that a dimension will never achieve. You don't know the exact measure, but you can know its maximum. So, use max-width and max-height.

Let's take an accordion menu and set the transition of its submenus heights, which I know is less than 1000px:


ul, li {
    display: block;
    margin: 0;
    padding: 0;
    width: 250px;
}
li {
    border-bottom: 1px solid lightgrey;
}
li > ul {
    max-height: 0;
    overflow: hidden;
    text-indent: .5em;
    transition: max-height 1s;
}
li:hover > ul {
    max-height: 1000px;
}

Beyond the essential properties, I added some ones for a better visualization of the effect you can see on this dabblet.

This works because the minimum value of max-height is the same as the result of height: auto.

Percentage measures just work if the containing element has its measure explicitly set. From MDN again:

The percentage is calculated with respect to the height of the containing block. If the height of the containing block is not specified explicitly, the percentage value is treated as none.


update: be sure to read @johanberonius 's comment

1 Response
Add your response

Since the estimated max-height, 1000px in this example, must exceed the actual height with a good margin there will be a delay when transitioning down from this max-height before it starts to actually limit the real height.
This delay can be minimized using an easing curve with a steep leading edge:
transition-timing-function: cubic-bezier(0, 1, 0, 1)
Be sure not to use the same easing curve when transitioning up.

over 1 year ago ·