Transição CSS com largura ou altura automática

Definir a transição nas dimensões de um elemento que não tem suas dimensões especificamente definidas é um problema. Do MDN :

Além disso, o autovalor costuma ser um caso muito complexo. A especificação pede para não animar de e para tal valor. Alguns agentes de usuário, como aqueles baseados no Gecko, implementam esse requisito e outros, como aqueles baseados no WebKit, são menos rígidos. O uso de animações com autopode levar a resultados imprevisíveis, dependendo do navegador e de sua versão, e deve ser evitado.

Mas às vezes você simplesmente não conhece a dimensão do elemento. Eles são definidos por seu conteúdo.

O truque é que podemos, na maioria das vezes, adivinhar um valor que uma dimensão nunca alcançará. Você não sabe a medida exata, mas pode saber o seu máximo. Então, use max-widthe max-height.

Vamos pegar um menu de acordeão e definir a transição das alturas de seus submenus, que eu sei que é inferior a 1000 px:


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;
}

Além das propriedades essenciais, adicionei algumas para uma melhor visualização do efeito que você pode ver neste dabblet .

Isso funciona porque o valor mínimo de max-heighté o mesmo que o resultado de height: auto.

As medidas de porcentagem funcionam apenas se o elemento contido tiver sua medida explicitamente definida. De MDN novamente :

A porcentagem é calculada em relação à altura do bloco que o contém. Se a altura do bloco que o contém não for especificada explicitamente, o valor da porcentagem é tratado como nenhum.


atualização: certifique-se de ler o comentário de @johanberonius