Flip Cards
BeginnerTwo-sided cards with flip animations. Click to flip, swipe to approve/reject.
Demo
Source
vue
<script lang="ts" setup>
import { ref } from 'vue'
import { FlashCards, FlipCard } from 'vue3-flashcards'
import AnswerCard from './AnswerCard.vue'
import QuestionCard from './QuestionCard.vue'
const cards = ref([
{ text: 'What is the capital of France?', back: 'Paris', difficulty: 'Easy', category: 'Geography' },
{ text: 'What is 15 × 8?', back: '120', difficulty: 'Medium', category: 'Mathematics' },
{ text: 'Who wrote "Romeo and Juliet"?', back: 'William Shakespeare', difficulty: 'Easy', category: 'Literature' },
])
const waitAnimationEnd = ref(true)
const invertAxios = ref<false>(false)
</script>
<template>
<div class="w-full flex flex-col justify-center items-center py-20">
<div class="mb-8 bg-white dark:bg-gray-800 p-4 rounded-xl shadow-md">
<label class="flex items-center gap-3 cursor-pointer mb-1">
<input
v-model="waitAnimationEnd"
type="checkbox"
class="toggle toggle-primary"
>
<span class="font-medium text-gray-700 dark:text-gray-300">Wait for animation end</span>
</label>
<label class="flex items-center gap-3 cursor-pointer">
<input
v-model="invertAxios"
type="checkbox"
class="toggle toggle-primary"
>
<span class="font-medium text-gray-700 dark:text-gray-300">Invert axis</span>
</label>
</div>
<div class="max-w-sm w-full">
<FlashCards :items="cards">
<template #default="{ item }">
<FlipCard :wait-animation-end="waitAnimationEnd" :flip-axis="invertAxios ? 'x' : 'y'">
<template #front>
<QuestionCard :item="item" />
</template>
<template #back>
<AnswerCard :item="item" />
</template>
</FlipCard>
</template>
</FlashCards>
</div>
</div>
</template>vue
<script setup lang="ts">
interface QuizItem {
text: string
back: string
difficulty: string
category: string
}
defineProps<{
item: QuizItem
}>()
</script>
<template>
<div class="relative overflow-hidden rounded-2xl shadow-2xl h-72 bg-gradient-to-br from-blue-500 to-purple-600 text-white transform transition-all duration-300">
<!-- Question mark icon -->
<div class="absolute top-4 right-4 w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
<span class="text-white font-bold">?</span>
</div>
<!-- Category tag -->
<div class="absolute top-4 left-4">
<span class="px-3 py-1 bg-white/20 rounded-full text-sm font-medium">
{{ item.category }}
</span>
</div>
<!-- Question content -->
<div class="p-6 h-full flex flex-col justify-center items-center text-center">
<h2 class="text-lg font-bold mb-4 leading-relaxed">
{{ item.text }}
</h2>
<div class="text-sm opacity-80">
Tap to reveal answer
</div>
</div>
<!-- Difficulty indicator -->
<div class="absolute bottom-4 left-4">
<div class="flex items-center gap-2">
<div class="w-2 h-2 bg-white rounded-full" />
<div :class="item.difficulty === 'Easy' ? 'w-2 h-2 bg-green-400 rounded-full' : 'w-2 h-2 bg-white/50 rounded-full'" />
<div :class="item.difficulty === 'Medium' ? 'w-2 h-2 bg-yellow-400 rounded-full' : 'w-2 h-2 bg-white/50 rounded-full'" />
<div :class="item.difficulty === 'Hard' ? 'w-2 h-2 bg-red-400 rounded-full' : 'w-2 h-2 bg-white/50 rounded-full'" />
</div>
</div>
</div>
</template>vue
<script setup lang="ts">
interface QuizItem {
text: string
back: string
difficulty: string
category: string
}
defineProps<{
item: QuizItem
}>()
</script>
<template>
<div class="relative overflow-hidden rounded-2xl shadow-2xl h-72 bg-gradient-to-br from-emerald-500 to-teal-600 text-white transform transition-all duration-300">
<!-- Answer checkmark icon -->
<div class="absolute top-4 right-4 w-8 h-8 bg-white/20 rounded-full flex items-center justify-center">
<span class="text-white font-bold">✓</span>
</div>
<!-- Category tag -->
<div class="absolute top-4 left-4">
<span class="px-3 py-1 bg-white/20 rounded-full text-sm font-medium">
{{ item.category }}
</span>
</div>
<!-- Answer content -->
<div class="p-6 h-full flex flex-col justify-center items-center text-center">
<div class="text-sm opacity-80 mb-2">
Answer:
</div>
<h2 class="text-2xl font-bold mb-4">
{{ item.back }}
</h2>
<div class="text-sm opacity-80">
Swipe to continue
</div>
</div>
<!-- Difficulty indicator -->
<div class="absolute bottom-4 left-4">
<span class="px-2 py-1 bg-white/20 rounded-full text-xs">
{{ item.difficulty }}
</span>
</div>
</div>
</template>Key Concepts
- FlipCard component: Independent two-sided card
- flip-axis="x": Horizontal flip animation
- flip() method: Programmatically trigger flip
- Perfect for: flashcards, quiz apps, reveal content