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 withauto
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
Written by Robson Sobral
Related protips
1 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.