Search code examples
vue.jsvue-routeranimate.css

Vue.js router transition fade gap


I'm using the amazing transition to slide router pages in vue.js

<template>
  <div>
    <header-comp></header-comp>
    <transition
            name="custom-classes-transition"
            mode="out-in"
            enter-active-class="animated slideInLeft"
            leave-active-class="animated slideOutRight"
    >
        <router-view></router-view>
    </transition>
    <footer-comp></footer-comp>
  </div>
</template>

<style>
    @import 'https://cdn.jsdelivr.net/npm/[email protected]';
</style>

It works very nice and smooth, but... the new coming page enter when the first one is totally gone. This made a gap between transition.

In Vue manual: Transition-Modes there are a few examples. I need to replicate the third button example but I'm missing the mode I have to use.

Any suggestion?


Solution

  • The main problem with your transitioning elements is that you want them to occupy the same space in DOM at the same time (even if, visually, one enters and one exists - that's only done through transforms but the two elements need to occupy the same space in DOM).

    Therefore you need to give one of them position:absolute and use CSS to size and position it correctly, to match the exact position and size it would have when not having position:absolute (which is what it will have when not trasitioning).

    Here's a working example. Note yours might need different styles applied to a different element.
    Since you haven't provided a minimal, reproducible example with your own markup, there's no way to know.

    In the example above, I gave the subsequent <div> (the entering one)

    position: absolute;
    width: 100%;
    top: 60px;
    left: 0;
    

    If you choose to wrap all your <router-view>s into a common wrapper element with position:relative, top would need to be 0 (in the example 60px is accounting for <nav>'s height).

    Note: and yes, as others already pointed, you don't need mode="in-out". But that still leaves you with the positioning issue.


    Edit: I've played with two more examples.

    • one using a flexbox container of height:100vh where top and bottom elements don't grow and middle one does. When middle element is too big, it becomes scrollable.
    • another one where I played with the transition effects and Bootstrap Vue.