Search code examples
sassvuejs3vuejs-transition-group

Vue TransitionGroup not working properly because of css transition


After debugging for several hours I concluded that Vue does not work well with the CSS transition property.

The transition group: https://vuejs.org/guide/built-ins/transition-group

<TransitionGroup name="store" tag="div">
  <button v-for="item in store.items" :key="item">{{ item.name}}</button>
</TransitionGroup>

Vue3 transition classes: css-based-transitions

.store-move,
.store-enter-active,
.store-leave-active {
  transition:
    opacity 500ms ease,
    transform 500ms ease; // reference 1
}

.store-enter-from,
.store-leave-to {
  opacity: 0;
  transform: translateY(2rem);
}

.store-leave-active {
  position: absolute;
}

Relevant styles on the buttons (using scss):

button {
  display: block;
  transition: transform 150ms ease; // reference 2

  &:hover {
   transform: scale(1.2);
  }

  &:active {
    transform: scale(0.9);
  }
}

Option A: The transition group does not work at all unless you put !important on the vue transition class (reference 1). Option B: Comment out the transition on the button selector (reference 2).

In both scenarios the transition group does not work as expected because of the shared transform property on the transition.

Option C: When commenting out everything below reference 1 aswell, the transition group works perfectly.

I have not yet found any workaround to this problem.


Solution

  • You're experiencing a classic specificity issue.

    The reason why is not clear based on the code fragments you included in your question.
    But as I happen to have the benefit of also being your college lecturer on this subject (🤫), I had a look at your original code base.

    Your button transition property has following selector:
    .store .stall .window .shelf button[data-v-687e7f7b]
    With a specificity of 051.

    Your TransitionGroup selectors have following selectors:
    .store-move[data-v-687e7f7b] etc.
    With a specificity of 020.

    That is why adding !important solves your issue (although you should not use it).
    Move or update the TransitionGroup classes so they have a higher specificity than your button.

    The real issue however is that you created somewhat of a CSS nesting hell. I suggest refactoring into more components (AppButton for instance), keep your selectors clean and your nesting minimal.