Hola Habr!
Quiero compartir otra forma de crear una transición CSS de la propiedad de
height
de
0px
a
auto
.
Enfrenté este problema al desarrollar componentes web TreeView y DataGrid. En TreeView, decidí hacer una expansión / colapso suave de los nodos, y en un DataGrid - filas con contenido adicional. Después de leer Internet, encontré varios métodos de implementación, los principales a través de la
max-height
y en javascript. Se descartó la implementación de JavaScript: hay CSS con soporte para transiciones y animaciones.
max-height
restante, especialmente en los ejemplos con menús desplegables, todo funciona.
En TreeView, cada nodo tiene un anidamiento ilimitado, por lo que no puede determinar inmediatamente la altura máxima de su contenido, e incluso si establece la
max-height
en muy grande, habrá problemas con la animación de transición. Además, si expande los nodos secundarios, la altura del padre aumentará y puede superponerse
max-height
. Nos guste o no,
max-height
no
max-height
adecuada. DataGrid tiene el mismo problema: puede haber contenido adicional en una fila. Necesita
height:auto
!
Entonces, comencemos a implementar la transición en la propiedad de
height
de
0px
a
auto
. Considere un ejemplo simple.
Dejar:
elBlock: HTMLDivElement
- bloque para elBlock: HTMLDivElement
/ contraer;elToggle: HTMLButtonElement
: botón para alternar el estado.
Defina una clase css para el bloque en el que establecemos el recorte del contenido y la transición en sí:
.block { overflow: hidden; transition: height 500ms ease; }
Describimos el
onClick
eventos
onClick
para
elToggle
:
elToggle.addEventListener("click", () => { if (elBlock.style.height === "0px") { elBlock.style.height = `${ elBlock.scrollHeight }px` } else { elBlock.style.height = `${ elBlock.scrollHeight }px`; window.getComputedStyle(elBlock, null).getPropertyValue("height"); elBlock.style.height = "0"; } });
Queda por agregar la
height:auto
retorno
height:auto
después de la transición:
elBlock.addEventListener("transitionend", () => { if (elBlock.style.height !== "0px") { elBlock.style.height = "auto" } });
Bueno, eso es todo, ahora la expansión / colapso del bloque funciona como debería y no depende del tamaño del contenido.
Figura 1 - Un ejemplo de nodos expandibles / colapsados en un TreeViewVale la pena señalar las desventajas de este enfoque:
- usando javascript, me gustaría solo css;
- durante la transición, el contenido (su altura,
scrollHeight
) puede cambiar y después de su finalización, si regresa auto
, la altura del bloque cambiará dramáticamente en una dirección u otra. Para evitar este efecto, debe realizar un seguimiento del cambio en scrollHeight
y cambiar la height
. Como muestra la práctica, generalmente las transiciones de expansión / colapso toman 0.5 s cada una, y durante este tiempo es poco probable que el usuario tenga tiempo de cambiar algo adentro, por ejemplo, en el caso de TreeView, expanda el nodo secundario.
Gracias por su atencion!