I'm using the following code to animate v-if element by reducing the height to 0px from. The animation works fine. But the problem is I've to specify the initial height of the element is CSS. For one element this is ok, But I want to apply this animation to multiple elements. How can I fix this? So that whatever be the height, animation works fine!
<transition name="fadeHeight" mode="out-in">
<div v-if="something">
<p>something over here where the height is not constant</p>
</div>
</transition>
.fadeHeight-enter-active,
.fadeHeight-leave-active {
transition: all 0.2s;
height: 230px;
}
.fadeHeight-enter,
.fadeHeight-leave-to
{
opacity: 0;
height: 0px;
}
To get an element's height with Vue. js, we can assign a ref to the element we want to get the height for. Then we can get the height with the clientHeight property of the element that's been assigned the ref. We assigned the ref with the ref prop set to a name.
We can't transition height , but we can transition max-height , since it has an explicit value. At any given moment, the actual height of the element will be the minimum of the height and the max-height .
For animate the "height" of element with CSS Transitions you need use "max-height". If use the "height: auto", the effect not works. Is necessary some value for the CSS create a CSS animate, and you can use "max-height" with a great value for emulate this effect.
It doesn't look like you've posted all the code, but hopefully I understand the goal.
Try moving the transition to the max-height
property:
.fadeHeight-enter-active,
.fadeHeight-leave-active {
transition: all 0.2s;
max-height: 230px;
}
.fadeHeight-enter,
.fadeHeight-leave-to
{
opacity: 0;
max-height: 0px;
}
as long as you set a max height to be larger than the tallest element, it should accomplish what you need. Note that you may also want to use overflow:hidden
as well. If you have dramatic variation of the actual height of the elements, this solution may not be the best, as it will make the animation duration/delay appear very different.
https://jsfiddle.net/7ap15qq0/4/
@ryantdecker has the most common answer available. I prefer doing less code though and do class binding instead:
<template>
<!-- isShowing either a data or computed... -->
<div class="foo" :class="{'showing': isShowing', 'hidden': !isShowing}">
<p>
something over here where the height is not constant
</p>
</div>
</template>
...
<style>
.foo {
height: auto;
transition: max-height 0.5s;
&.showing {
max-height: 200px; //MUST BE MORE THAN height:auto
}
&.hidden {
max-height: 0px;
}
}
</style>
A few customizations that can be done for even more control are:
:style="{'max-height': computedHeight}"
ease-in
and ease-out
with two different transitions
within the .showing
and .hidden
classes respectively.The first customization above can be used when you are using distinct items, like pictures, flex rows where the height can be seen via devtools and the height calculated. E.g.:
computed: {
/**
* @return {string} max height of the container in pixels if shown else zero
*/
calcedHeight()
{
const elHeight = 80;
const maxHeight = this.isShowing ? elHeight * this.elementCount : 0
const maxHeightPx = maxHeight + 'px'
return {
'max-height': maxHeightPx
}
}
}
This could easily be made into a component with isShowing
, elHeight
, and elCount
props at this point.
I am giving this it's own section because it might be all that is needed in regards to crazy long elements (think 5000px max-heights
):
&.showing {
transition: all 0.6s cubic-bezier(1, 0.01, 1, 0.01);
}
&.hidden {
transition: all 0.6s cubic-bezier(0.01, 1, 0.01, 1);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With