Skip to content

nv-dev-labs/vue-flipcard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vue FlipCard

An elegant and interactive Vue 3 flip-card component with support for drag interactions, clicks, and hover effects across 4 rotation directions.

⚠️ Client-only component: This component relies on DOM interactions and CSS 3D transforms. It cannot be rendered on the server and must be used only in client-side contexts.

Features

  • 4 flip directions: right, left, up, down
  • Multiple interactions: drag/swipe, click, hover
  • Mobile & Desktop: compatible with touch and mouse
  • Customizable: dimensions, styles, and transitions
  • High performance: GPU-accelerated CSS 3D transforms
  • Fully typed: complete TypeScript support

Installation

npm install @nv-dev/vue-flipcard
# or
yarn add @nv-dev/vue-flipcard
# or
pnpm add @nv-dev/vue-flipcard

Usage

For Vue 3 apps

Import the component

import VFlipCard from '@nv-dev/vue-flipcard'

Or register globally:

import { createApp } from 'vue'
import VFlipCard from '@nv-dev/vue-flipcard'

const app = createApp(App)
app.use(VFlipCard)
app.mount('#app')

For Nuxt 3 (Auto-import)

Add the module to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: [
    '@nv-dev/vue-flipcard'
  ],
})

The VFlipCard component will be automatically imported throughout your Nuxt app. No manual imports needed!

Since this is a client-only component, wrap it with <ClientOnly>:

<template>
  <ClientOnly>
    <VFlipCard flip-side="right" active-click>
      <!-- CODE -->
    </VFlipCard>
  </ClientOnly>
</template>

Basic example

<template>
  <VFlipCard
    width="200px"
    height="150px"
    flip-side="right"
    active-click
    active-drag
  >
    <template #front>
      <p>Front side</p>
    </template>
    <template #back>
      <p>Back side</p>
    </template>
  </VFlipCard>
</template>

Props

Prop Type Default Description
width String '200px' Card width
height String '150px' Card height
flipSide 'left' | 'right' | 'up' | 'down' 'right' Flip direction
activeClick Boolean false Enable flip on click
activeDrag Boolean false Enable flip on drag/swipe (mobile only)
activeHover Boolean false Enable flip on hover (desktop only)

Slots

#front

Content displayed on the front face of the card.

#back

Content displayed on the back face of the card.

Client-only Component

This component is client-only for now and cannot be server-side rendered (SSR).

Using with Nuxt 3

Always wrap the component with <ClientOnly>:

<template>
  <ClientOnly>
    <VFlipCard flip-side="right" active-click>
      <template #front>Front content</template>
      <template #back>Back content</template>
    </VFlipCard>
  </ClientOnly>
</template>

This prevents hydration mismatches and ensures your component renders correctly.

Examples

Flip on click

<VFlipCard flip-side="right" active-click>
  <template #front><img src="front.jpg" /></template>
  <template #back><img src="back.jpg" /></template>
</VFlipCard>

Flip on hover (desktop)

<VFlipCard flip-side="up" active-hover>
  <template #front>Hover me</template>
  <template #back>Flipped!</template>
</VFlipCard>

Flip on swipe (mobile)

<VFlipCard flip-side="left" active-drag width="300px" height="200px">
  <template #front>Swipe left</template>
  <template #back>Content</template>
</VFlipCard>

All interactions

<VFlipCard
  flip-side="down"
  active-click
  active-drag
  active-hover
>
  <template #front>Front</template>
  <template #back>Back</template>
</VFlipCard>

Flip directions

  • right: Drag right side towards you (clockwise, rotateY)
  • left: Drag left side towards you (counter-clockwise, rotateY)
  • up: Drag top towards you (upward, rotateX)
  • down: Drag bottom towards you (downward, rotateX)

Behavior

Click

  • Toggles between front and back
  • Works on mobile and desktop

Drag/Swipe

  • Move your finger in the flip direction
  • Drag distance is proportional to the card size (width for left/right, height for up/down)
  • 90-degree threshold to determine final side
  • Smooth animation with configurable transitions

Hover

  • Desktop only (automatically detected)
  • Shows back on hover, returns to front on leave

Styling

The component uses CSS classes for easy customization:

.flip-card-face {
  border-radius: 6px;
  box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.front {
  background: #fff;
}

.back {
  background: #f7f7f7;
}

Customize with scoped CSS:

<style scoped>
:deep(.flip-card-face) {
  border: 2px solid #your-color;
}
</style>

Events

The component emits events when the card flips:

Event Payload Description
flip:front Emitted when the card flips to show the front face
flip:back Emitted when the card flips to show the back face

Usage

<script setup>
const onFlipToFront = () => {
  console.log('Card flipped to front')
}

const onFlipToBack = () => {
  console.log('Card flipped to back')
}
</script>

<template>
  <VFlipCard
    flip-side="right"
    active-click
    @flip:front="onFlipToFront"
    @flip:back="onFlipToBack"
  >
    <template #front>Front</template>
    <template #back>Back</template>
  </VFlipCard>
</template>

v-model: Programmatic State Control

The component supports v-model binding for two-way synchronization of the card's flip state. This allows you to control the card programmatically from your Vue component.

State values

  • true: Card is flipped to show the back face
  • false: Card is showing the front face

Usage

<script setup>
import { ref } from 'vue'
import VFlipCard from '@nv-dev/vue-flipcard'

const isFlipped = ref(false)
</script>

<template>
  <div>
    <button @click="isFlipped = !isFlipped">
      {{ isFlipped ? 'Show Front' : 'Show Back' }}
    </button>

    <VFlipCard
      v-model="isFlipped"
      flip-side="right"
      active-click
      active-drag
    >
      <template #front>Front side</template>
      <template #back>Back side</template>
    </VFlipCard>
  </div>
</template>

Two-way binding

The component automatically updates the v-model value when:

  • User clicks the card (with activeClick)
  • User drags/swipes past 90 degrees (with activeDrag)
  • User hovers (with activeHover on desktop)

You can also update the state programmatically:

const isFlipped = ref(false)

const flipCard = () => {
  isFlipped.value = true
}

const resetCard = () => {
  isFlipped.value = false
}

Dynamic state management

<script setup>
import { ref } from 'vue'

const card1State = ref(false)
const card2State = ref(false)

const toggleAll = () => {
  card1State.value = !card1State.value
  card2State.value = !card2State.value
}
</script>

<template>
  <div>
    <button @click="toggleAll">Toggle all cards</button>

    <VFlipCard v-model="card1State" flip-side="right">
      <template #front>Card 1 Front</template>
      <template #back>Card 1 Back</template>
    </VFlipCard>

    <VFlipCard v-model="card2State" flip-side="left">
      <template #front>Card 2 Front</template>
      <template #back>Card 2 Back</template>
    </VFlipCard>
  </div>
</template>

Browser Support

  • Chrome/Edge (latest versions)
  • Firefox (latest versions)
  • Safari (latest versions)
  • Mobile iOS/Android with Touch Events support

Performance

  • Uses CSS 3D transforms for GPU-accelerated animations
  • Smooth CSS transitions (0.6s cubic-bezier by default)
  • Minimal JavaScript computation

License

MIT

Author

Nicolas VETROFF

Repository

https://github.com/nicolas-vetroff/vue-flipcard

Contributing

This project is open to improvements and suggestions. Feel free to open issues.

About

An interactive Vue 3 flip-card component

Topics

Resources

Stars

Watchers

Forks

Contributors