¿Cómo puedo hacer la transición de altura: 0; a altura: auto; usando CSS?

Resuelto Hailwood asked hace 14 años • 46 respuestas

Estoy intentando deslizarme <ul>hacia abajo usando transiciones CSS.

El <ul>comienza a las height: 0;. Al pasar el mouse, la altura se establece en height:auto;. Sin embargo, esto hace que simplemente aparezca, no una transición,

Si lo hago desde height: 40px;hasta height: auto;, se deslizará hacia arriba height: 0;y luego, de repente, saltará a la altura correcta.

¿De qué otra manera podría hacer esto sin usar JavaScript?

#child0 {
  height: 0;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent0:hover #child0 {
  height: auto;
}
#child40 {
  height: 40px;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent40:hover #child40 {
  height: auto;
}
h1 {
  font-weight: bold;
}
The only difference between the two snippets of CSS is one has height: 0, the other height: 40.
<hr>
<div id="parent0">
  <h1>Hover me (height: 0)</h1>
  <div id="child0">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>
<hr>
<div id="parent40">
  <h1>Hover me (height: 40)</h1>
  <div id="child40">Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>Some content
    <br>
  </div>
</div>
Expandir fragmento

Hailwood avatar Aug 18 '10 09:08 Hailwood
Aceptado

Usar max-heighten la transición y no height. Y establezca un valor max-heightpara algo más grande de lo que jamás tendrá su caja.

Vea la demostración de JSFiddle proporcionada por Chris Jordan en otra respuesta aquí.

#menu #list {
    max-height: 0;
    transition: max-height 0.15s ease-out;
    overflow: hidden;
    background: #d5d5d5;
}

#menu:hover #list {
    max-height: 500px;
    transition: max-height 0.25s ease-in;
}
<div id="menu">
    <a>hover me</a>
    <ul id="list">
        <!-- Create a bunch, or not a bunch, of li's to see the timing. -->
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>
Expandir fragmento

jake avatar Nov 30 '2011 18:11 jake

Deberías usar scaleY en su lugar.

ul {
  background-color: #eee;
  transform: scaleY(0);    
  transform-origin: top;
  transition: transform 0.26s ease;
}
p:hover ~ ul {
  transform: scaleY(1);
}
<p>Hover This</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>
Expandir fragmento

Creé una versión con prefijo de proveedor del código anterior en jsfiddle y cambié su jsfiddle para usar scaleY en lugar de height.

Editar A algunas personas no les gusta cómoscaleYse transforma el contenido. Si eso es un problema, sugiero usarloclipen su lugar.

ul {
  clip: rect(auto, auto, 0, auto);
  position: absolute;
  margin: -1rem 0;
  padding: .5rem;

  color: white;

  background-color: rgba(0, 0, 0, 0.8);

  transition-property: clip;
  transition-duration: 0.5s;
  transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
h3:hover ~ ul,
h3:active ~ ul,
ul:hover {
  clip: rect(auto, auto, 10rem, auto);
}
<h3>Hover here</h3>
<ul>
  <li>This list</li>
  <li>is clipped.</li>
  <li>A clip transition</li>
  <li>will show it</li>
</ul>
<p>
  Some text...
</p>
Expandir fragmento

dotnetCarpenter avatar Jun 23 '2013 10:06 dotnetCarpenter

Actualmente no puedes animar la altura cuando una de las alturas involucradas es auto, debes establecer dos alturas explícitas.

robertc avatar Aug 18 '2010 12:08 robertc

La solución que siempre he usado fue primero atenuar y luego reducir los valores font-sizey . No parece lo mismo que un paño, pero funciona sin estática ni archivos .paddingmarginheightmax-height

Ejemplo de trabajo:

/* final display */
#menu #list {
    margin: .5em 1em;
    padding: 1em;
}

/* hide */
#menu:not(:hover) #list {
    font-size: 0;
    margin: 0;
    opacity: 0;
    padding: 0;
    /* fade out, then shrink */
    transition: opacity .25s,
                font-size .5s .25s,
                margin .5s .25s,
                padding .5s .25s;
}

/* reveal */
#menu:hover #list {
    /* unshrink, then fade in */
    transition: font-size .25s,
                margin .25s,
                padding .25s,
                opacity .5s .25s;
}
<div id="menu">
    <b>hover me</b>
    <ul id="list">
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>

<p>Another paragraph...</p>
Expandir fragmento

Steven Vachon avatar May 29 '2015 14:05 Steven Vachon