Skip to content
Advertisement

Flip Card Component in VueJs 3

I want to achieve a Flip card component like the one here by developing a generic Vue Component, but I’m confused about how can I assign a whole face component (front/back) as a back or front face of the card, and how can I lock the flipping property (as an option), an example of the face (front/back) is:

<div id="planflex" :style="style">
    <div class="block">
            <h2> {{ action_id }} </h2>
    </div>
    <div class="block">
        <img 
        :src="require(`../assets/legos/2x${size}${color}.png`)" 
        alt="legos" 
        id="lego">
    </div>
    <div class="block " :id="action_id" @click="choose()">
        <h3> {{ actor }} </h3>
    </div>
</div>

Can you please tell me how can I achieve that properly? thanks in advance.

The FlipCard.vue Vue component I have tried to develop:

<template>
    <div id="flashcard" class="container" @dblclick="toggleCard()">
  
      <transition name="flip">
        <div v-bind:key="flipped" class="card">
            {{ flipped ? back : front }}
        </div>
      </transition>  
  </div>
</template>

<script>
  export default {
      name: "FlipCard",
      props: {
          front: {
              type: Object,
              required: true
          },
          back: {
              type: Object,
              required: true
          },
          flipped: {
              type: Boolean,
              default: false,
          },
      },
      methods: {
          toggleCard() {
              this.flipped = !this.flipped;
          },
      }
  }
</script>

Style.css

<style>
body {
    font-family: 'Montserrat', sans-serif;
    text-align: center;
  }
  
  ul {
    padding-left: 0;
    display: flex;
    flex-flow: row wrap;
  }
  
  li {
    list-style-type: none;
    padding: 10px 10px;
    transition: all 0.3s ease;
  }
  
  .container {
    max-width: 100%;
    padding: 2em;
  }
  
  .card {
    display: block;
    width: 150px;
    height: 175px;
    padding: 80px 50px;
    background-color: #51aae5;
    border-radius: 7px;
    margin: 5px;
    text-align: center;
    line-height: 27px;
    cursor: pointer;
    position: relative;
    color: #fff;
    font-weight: 600;
    font-size: 20px;
    -webkit-box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5);
    -moz-box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5);
    box-shadow: 9px 10px 22px -8px rgba(209,193,209,.5);
    will-change: transform;
  }
  
  li:hover{
    transform: scale(1.1);
  }
  
  li:nth-child(-n+3) .card{
    background-color: #e65f51;
    }
  
  li:nth-child(2n+1) .card{
    background-color: #a17de9;
    }
  
  li:nth-child(4n) .card{
    background-color: #feca34;
    }
  
  li:nth-child(5n-2) .card{
    background-color: #51aae5;
    }
  
  li:nth-child(4n+4) .card{
    background-color: #feca34;
    }
  
  li:nth-child(-7n+7) .card{
    background-color: #e46055;
    }
  
  .delete-card {
    position: absolute;
    right: 0;
    top: 0;
    padding: 10px 15px;
    opacity: .4;
    transition: all 0.5s ease;
  }
  
  .delete-card:hover, .error {
    opacity: 1;
    transform: rotate(360deg);
  }
  
  .flip-enter-active {
    transition: all 0.4s ease;
  }
  
  .flip-leave-active {
    display: none;
  }
  
  .flip-enter, .flip-leave {
    transform: rotateY(180deg);
    opacity: 0;
  
  }
</style>

Advertisement

Answer

Your card face looks good to put into a new component and then flipCard.vue can display that component, front or back, as a dynamic component

flipCard.vue

<div v-bind:key="flipped" class="card">
  <component :is="cardSide" />
</div>
<script>
import cardFront from "@/components/cardFront.vue";
import cardBack from "@/components/cardBack.vue";

export default {
  computed: {
    cardSide() {
      if (this.flipped) return cardFront;
      else return cardBack;
    },
  }
};
</script>

more detailed codesandbox here.

Another option is to use slots to display dynamic component content.

Parent component

<flip-card>
  <template v-slot:front>
    <cardFront />
  </template>
  <template v-slot:back>
    <cardBack />
  </template>
</flip-card>

flipCard.vue

<template>
  <div id="flashcard" class="container" @click="toggleCard()">
    <transition name="flip">
      <div v-bind:key="flipped" class="card">
        <slot v-if="!flipped" name="front"></slot>
        <slot v-else name="back"></slot>
      </div>
    </transition>
  </div>
</template>

another more detailed codesandbox

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement