I'm trying to make two elements that alternate on an opposing v-show predicate to transition between themselves in terms of height, but I'm unable to find a good solution for this. This may be a bit elementary, but I'm inexperienced with transitions/animations, and I can't find any good examples to guide me here.
HTML:
<div id="app">
<div class="history">
<p>
How to make the green bordered area transition smoothly between different height in states A and B?
</p>
<div class="placeholder-content">
</div>
</div>
<div class="interaction">
<button @click="(show_A ? show_A = false : show_A = true);">
Cycle states
</button>
<transition name="swap">
<div v-show="show_A" class="interaction-A"> A </div>
</transition>
<transition name="swap">
<div v-show="!show_A" class="interaction-B"> B </div>
</transition>
</div>
</div>
CSS:
.swap-enter{
}
.swap-leave-to{
}
.swap-enter-active{
}
.swap-leave-active{
}
.swap-move{
}
I've formulated the problem in a fiddle:
https://fiddle.jshell.net/jensmtg/7zun5c9f/
There's a few critical mistakes in your code.
First, you need to use one transition element, not two, since you want the transition to occur IN the transition element, not ACROSS multiple transition elements, even though it involves them.
HTML:
<div class="interaction" v-bind:class="{ show_B: !show_A }">
<button @click="(show_A ? show_A = false : show_A = true);">
Cycle states
</button>
<transition name="fade">
<div v-if="show_A" class="interaction-A" key="a"> A </div>
<div v-else class="interaction-B" key="b"> B </div>
</transition>
</div>
Second, you'll need to apply the key
attribute to each element that you want to transition with a unique key, so that Vue recognizes that they are different.
I've cleaned up your code and used v-if
and v-else
to ensure that the elements are being torn down.
Finally, using a fade transition gives you a nice smooth change that accounts for the height difference.
CSS:
.interaction {
border: 10px solid lightgreen;
display: flex;
flex: 1 0 auto;
max-height: 225px;
transition: max-height 0.25s ease-out;
}
.interaction.show_B {
max-height: 325px;
transition: max-height 0.15s ease-in;
}
.fade-enter-active, .fade-leave-active {
transition-property: opacity;
transition-duration: .10s;
}
.fade-enter-active {
transition-delay: .25s;
}
.fade-enter, .fade-leave-active {
opacity: 0;
}
In order to smoothly transition the outer container while we transition the inner elements, a class show_B
is applied when the content is toggled to differentiate between A
and B
child content.
<div class="interaction" v-bind:class="{ show_B: !show_A }">
We can use this to apply a transition and a new max size, resizing the outer content as the child content resizes:
.interaction.show_B {
max-height: 325px;
transition: max-height 0.15s ease-in;
}
You can see the working fiddle here.
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