Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Vue.js Basics Building a Flashcard App Flip Transition!

Why does v-show cause cards to disappear when "flipped," where v-if produces expected result (card flipping)?

When adding the flip transition, only v-if to toggle front/back produces the intended outcome (card flips, front card info disappears and back card info appears or vice versa).

However, when using v-show, the card does not flip, but disappears on click.

Using vue devtools in Chrome, the card still exists in array cards with flipped = true, so this isn't a matter of accidentally hitting the delete card button.

Any idea why this is?

This flips the card properly:

<transition name="flip">
    <p class="card" key="front" v-if="!card.flipped">
        {{card.front}}
        <span v-on:click="cards.splice(index, 1)" class="delete-card">X</span>
    </p>
    <p class="card" key="back" v-else>
        {{card.back}}
        <span v-on:click="cards.splice(index, 1)" class="delete-card">X</span>
    </p>
</transition>

This doesn't:

<transition name="flip">
    <p class="card" key="front" v-show="!card.flipped">
        {{card.front}}
        <span v-on:click="cards.splice(index, 1)" class="delete-card">X</span>
    </p>
    <p class="card" key="back" v-show="card.flipped">
        {{card.back}}
        <span v-on:click="cards.splice(index, 1)" class="delete-card">X</span>
    </p>
</transition>

1 Answer

Treasure Porth
STAFF
Treasure Porth
Treehouse Teacher

This has to do with the way the <transition> component works. If you look in your console, you should see the following error:

vue.js:584 [Vue warn]: <transition> can only be used on a single element. Use <transition-group> for lists.

When you use v-show, you're toggling the CSS display property on and off, so both paragraph elements (the front and back of the card) technically always exist in the DOM at the same time, you're just showing or hiding them (temporarily delete the <transition> element-- you'll see that both paragraphs are always there, but on click display: none is being added and removed from both elements).

The existence of two elements at once causes the <transition> component to throw a fit because it can only deal with one element at a time. With v-if and v-else, the front and backs of the cards are actually being added and removed from the DOM on click. This ensures that only one paragraph element at a time exists in the DOM, and the <transition> component is happy :D

The <transition-group> is designed to handle more than one element. Change <transition> to <transition-group> and v-show should work for you.

Thanks for the detailed explanation, Treasure. That makes a lot of sense!

Could I safely assume that <transition> performs better than <transition-group>? And if v-show is faster (for toggling anyway) vs . v-if, what would perform better in this case? <transition> with v-if or <transition-group> with v-show? Or is the difference negligible?