4

i'm working on a project where i have to render some components with an enter and leave animation, when a component enters the screen it has to enter form the bottom, and when it leaves, it has to do it going upwards, the desired behavior is that when i change the :is property of the component tag, the current component goes upwards and the next one comes from the bottom, the code looks like this:

<template>
  <div class="home">
    <transition name="section">
      <component :is="activeSection"></component>
    </transition>
  </div>
</template>

<script>
import comp1 from './comp1';
import comp2 from './comp2';

export default {
  components: {
    comp1,
    comp2
  },
  data() {
    activeSection: 'comp1'
  }
</script>

<style scoped>
  .section-enter {
    top: 100vh;
  }
  .section-enter-to {
    top: 0vh;
  }
  .section-enter-active {
    animation-name: 'slideIn';
    animation-duration: 1s;
  }
  .section-leave {
    top: 0vh;
  }
  .section-leave-active {
    animation-name: 'slideOut';
    animation-duration: 1s;
  }
  .section-leave-to {
    top: -100vh;
  }


  @keyframes slideIn {
    from {
      top: 100vh;
    }
    to {
      top: 0
    }
  }

  @keyframes slideOut {
    from {
      top: 0vh;
    }
    to {
      top: -100vh;
    }
  }
</style>

but the actual behavior is that the first component goes upwards but the second appears inmediatly after without animation.

if i render one at a time (not destructing one and rendering another with the same action) everything works perfectly. I dont know what is happening.

tony19
  • 125,647
  • 18
  • 229
  • 307
Carlos Pisarello
  • 1,254
  • 5
  • 20
  • 39
  • 1
    could you please put this somewhere like codesandbox so its easier to recreate and look into? – Gowri Jan 19 '19 at 01:40
  • Hey, in my case, I just had to add an `appear` attribute to my transition. Hope it may help the others having this issue! – l-portet Sep 10 '21 at 19:21

2 Answers2

5

There are a few problems in your CSS.

CSS Transitions and CSS Animations

A transition can be implemented using either CSS Transitions or CSS Animations. Your CSS incorrectly mixes the two concepts in this case.

In particular, the slideIn keyframes and .section-enter/.section-enter-to rules are effectively performing the same task of moving .section into view. However, this is missing a transition rule with a non-zero time, required to animate the change, so the change occurs immediately. The same issue exists for the slideOut keyframes and leave rules.

.section-enter {
  top: 100vh;
}
.section-enter-to {
  top: 0;
}
.section-enter-active {
  transition: .5s; /* MISSING RULE */
}

.section-leave {
  top: 0;
}
.section-leave-to {
  top: -100vh;
}
.section-leave-active {
  transition: .5s; /* MISSING RULE */
}

Removing the keyframes, and adding the missing rules (as shown above) would result in a working CSS Transition.

demo 1

Using CSS Animations

Alternatively, you could use keyframes with CSS Animations, where the animation is applied only by the *-active rules, and no *-enter/*-leave rules are used. Note your question contained unnecessary quotes in animation-name: 'slideIn';, which is invalid syntax and would be silently ignored (no animation occurs). I use a simpler shorthand in the following snippet (animation: slideIn 1s;).

.section-enter-active {
  animation: slideIn 1s;
}
.section-leave-active {
  animation: slideOut 1s;
}

@keyframes slideIn {
  from {
    top: 100vh;
  }
  to {
    top: 0;
  }
}
@keyframes slideOut {
  from {
    top: 0;
  }
  to {
    top: -100vh;
  }
}

demo 2

Optimizing CSS Transitions

You could also tweak your animation performance by using translateY instead of transitioning top.

/* top initially 0 in .wrapper */

.section-leave-active,
.section-enter-active {
  transition: .5s;
}
.section-enter {
  transform: translateY(100%);
}
.section-leave-to {
  transform: translateY(-100%);
}

demo 3

tony19
  • 125,647
  • 18
  • 229
  • 307
-1

Use a Mixin

Thanks for the explanation @tony19
please use a mixin for this so the logic can be repeated easily.
Also, your slideIn and slideOut can be combined by using reverse:

@mixin animationmixin($type:'animation', $style:'', $duration:1s) {
    
    @keyframes #{$type}-#{$style} { // register animation
        0% { opacity: 1;  transform: none; } // reset style
        100% { @content; } // custom style
    }
    
    .#{$style} { // add '.section'
        &-enter-active, &-leave-active { // add '.section-enter-active', ...
            transition: #{$duration};
        }
        &-enter, &-leave-to {
            animation: #{$type}-#{$style} #{$duration}; // use animation
        }
        &-leave, &-enter-to {
            animation: #{$type}-#{$style} #{$duration} reverse; // use animation in reverse 
        }
    }
}

Use it like this:

@include animationmixin($style:'section') { // set custom styling
    transform: translateY(100%);
};

And like this:

@include animationmixin($style:'fade') {
    opacity: 0;
    transform: scale(0.9);
};
Eagle_
  • 449
  • 1
  • 4
  • 12