I want to share another way to create a css transition of the
height
property from
0px
to
auto
.
Faced this problem when developing Web components TreeView and DataGrid. In TreeView, I decided to make a smooth expansion / collapse of nodes, and in a DataGrid - rows with additional content. After reading the Internet, I found several implementation methods, the main ones through the
max-height
and in javascript. The javascript implementation was ruled out - there is css with support for transitions and animations. Remained
max-height
, especially in the examples with drop-down menus everything works.
In the TreeView, each node has unlimited nesting, so you canβt immediately determine the maximum height of its contents, and even if you set the
max-height
to very large, there will be problems with the transition animation. Also, if you expand the child nodes, the height of the parent will increase and may overlap
max-height
. Anyway,
max-height
not suitable. DataGrid has the same problem - there can be any additional content in a row. Need
height:auto
!
So, let's start the implementation of the transition according to the
height
property from
0px
to
auto
. Consider a simple example.
Let:
-
elBlock: HTMLDivElement
- block to beelBlock: HTMLDivElement
/ collapsed; -
elToggle: HTMLButtonElement
- button toggle the status.
Define a css class for the block, in which we set the trimming of the content and the transition itself:
.block { overflow: hidden; transition: height 500ms ease; }
We describe the
onClick
event
onClick
for
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"; } });
It remains to add the return
height:auto
after the transition:
elBlock.addEventListener("transitionend", () => { if (elBlock.style.height !== "0px") { elBlock.style.height = "auto" } });
Well, thatβs all, now the expansion / collapse of the block works as it should and does not depend on the size of the content.
Figure 1 - An example of expanding / collapsing nodes in a TreeView
It is worth noting the disadvantages of this approach:
- using javascript, I would like only css;
- during the transition, the content (its height,
scrollHeight
) may change and after its completion, ifauto
returns, the height of the block will change dramatically in one direction or another. To avoid this effect, you need to track the change inscrollHeight
and change theheight
. As practice shows, usually expand / collapse transitions take 0.5 s each, and during this time the user is unlikely to have time to change something inside, for example, in the case of TreeView, expand the child node.
Thanks for attention!