I'm working on a "slide toggle" transition to get functionality similar to jQuery's .slideToggle() method. I have it working but there's one line needed to make it work and I'm not sure why. When I remove var neededForSomeReason = el.offsetHeight; from the enter() and leave() functions, there is no animation, the div just snaps open and closed.
Why is that line needed for the transition to work? And is there a way to make the transition work without it?
new Vue({
el: '#app',
data: {
height: 0,
open: false,
},
methods: {
toggle() {
this.open = !this.open;
},
beforeEnter: function(el) {
el.style.height = 'auto';
el.style.display = 'block';
this.height = el.offsetHeight;
el.style.height = '0px';
},
enter: function(el) {
// If this line is removed the transition doesn't work.
var removeToBreak = el.offsetHeight;
el.style.height = this.height + 'px';
},
afterEnter: function(el) {
el.style.height = 'auto';
},
beforeLeave: function(el) {
el.style.height = el.offsetHeight + 'px';
},
leave: function(el) {
// If this line is removed the transition doesn't work.
var removeToBreak = el.offsetHeight;
el.style.height = '0px';
},
},
})
.transition-height {
transition: height 250ms;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/0.5.3/tailwind.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app" class="p-4 bg-grey-light min-h-screen">
<div class="bg-white rounded-sm shadow overflow-hidden">
<div @click.prevent="toggle" class="px-8 py-4 bg-blue text-white">
Click to Toggle
</div>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
>
<div v-show="open" class="transition-height">
<div class="p-8 leading-normal text-grey-darker">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis orci vitae turpis laoreet mattis. Morbi quis viverra orci. Sed vitae tincidunt nisl. Phasellus lobortis nisi mauris, non semper neque maximus at. Integer neque enim, tristique a dui sed, ultrices eleifend dolor. Mauris non tristique leo. Ut erat quam, feugiat eget venenatis eu, euismod et tortor.
</div>
</div>
</transition>
</div>
</div>
console.log(el);console.log(el.offsetHeight);console.log(el);in place of the two breaking assignment operations. What you'll likely notice is that theoffsetHeightproperty on the twoelcalls remains the same, and that theel.offsetHeightcall differs. If the offsetHeight is 160 when open, you'll see 160 when opening onelbut 0 onel.offsetHeight, and when closing you'll see 0 oneland160onel.offsetHeight.offsetHeightproperty directly forces Vue to perform a calculation that is ordinarily deferred until the node is rendered, allowing your transition methods to pick up on the change earlier. As for why it requires seeing theoffsetHeightchange in order to work properly, I don't have an answer. Hopefully this gives you a direction to look into, though :)