Skip to content

Transitions

Advanced

Custom CSS animations with different transition styles.

Demo

Source
vue
<script setup>
import { ref } from 'vue'
import FlashCards from '../../src/FlashCards.vue'
import TransitionCard from './TransitionCard.vue'

const selectedTransition = ref('fast-rotate')

const cards = [
  { id: 1, title: 'Fast Rotate', description: 'Cards spin rapidly while exiting', color: '#FF6B6B' },
  { id: 2, title: 'Scale to Zero', description: 'Cards shrink to nothing', color: '#4ECDC4' },
  { id: 3, title: '3D Flip', description: 'Cards flip in 3D space', color: '#45B7D1' },
  { id: 4, title: 'Elastic Bounce', description: 'Cards bounce with elastic effect', color: '#FFA726' },
  { id: 5, title: 'Custom Effects', description: 'Combine multiple animations', color: '#AB47BC' },
]
</script>

<template>
  <div class="max-w-lg mx-auto p-6 transition-effects-example">
    <div class="text-center mb-8">
      <h2 class="text-3xl font-bold text-base-content mb-2">
        Custom Transition Effects
      </h2>
      <p class="text-base-content/70">
        Experiment with different transition styles
      </p>
    </div>

    <div class="bg-base-200 p-6 rounded-2xl mb-8">
      <div class="grid grid-cols-2 gap-4">
        <label class="label cursor-pointer">
          <input
            v-model="selectedTransition"
            type="radio"
            value="fast-rotate"
            class="radio radio-primary"
          >
          <span class="label-text ml-2">Fast Rotate</span>
        </label>
        <label class="label cursor-pointer">
          <input
            v-model="selectedTransition"
            type="radio"
            value="scale-out"
            class="radio radio-secondary"
          >
          <span class="label-text ml-2">Scale to Zero</span>
        </label>
        <label class="label cursor-pointer">
          <input
            v-model="selectedTransition"
            type="radio"
            value="flip-3d"
            class="radio radio-accent"
          >
          <span class="label-text ml-2">3D Flip</span>
        </label>
        <label class="label cursor-pointer">
          <input
            v-model="selectedTransition"
            type="radio"
            value="elastic-bounce"
            class="radio radio-info"
          >
          <span class="label-text ml-2">Elastic Bounce</span>
        </label>
      </div>
    </div>

    <div class="h-96 w-full relative">
      <FlashCards
        :items="cards"
        :class="selectedTransition"
        loop
      >
        <template #default="{ item }">
          <TransitionCard :card="item" />
        </template>
      </FlashCards>
    </div>
  </div>
</template>

<style>
/* Fast Rotate Animation */
.fast-rotate .flash-card-animation--right { animation: fast-rotate-right 0.4s linear forwards !important; transform-origin: 50% 50% !important; }
.fast-rotate .flash-card-animation--left { animation: fast-rotate-left 0.4s linear forwards !important; transform-origin: 50% 50% !important; }
.fast-rotate .flash-card-animation--right-restore { animation: fast-rotate-restore-right 0.4s linear forwards !important; transform-origin: 50% 50% !important; }
.fast-rotate .flash-card-animation--left-restore { animation: fast-rotate-restore-left 0.4s linear forwards !important; transform-origin: 50% 50% !important; }

@keyframes fast-rotate-right { 0%{opacity:1;} 100%{transform:translateX(300px) rotate(360deg);opacity:0;} }
@keyframes fast-rotate-left { 0%{opacity:1;} 100%{transform:translateX(-300px) rotate(-360deg);opacity:0;} }
@keyframes fast-rotate-restore-right { 0%{transform:translateX(300px) rotate(360deg);opacity:0;} 100%{transform:translateX(0) rotate(0deg);opacity:1;} }
@keyframes fast-rotate-restore-left { 0%{transform:translateX(-300px) rotate(-360deg);opacity:0;} 100%{transform:translateX(0) rotate(0deg);opacity:1;} }

/* Scale Out Animation */
.scale-out .flash-card-animation--right { animation: scale-out-right 0.3s cubic-bezier(0.25,0.46,0.45,0.94) forwards !important; }
.scale-out .flash-card-animation--left { animation: scale-out-left 0.3s cubic-bezier(0.25,0.46,0.45,0.94) forwards !important; }
.scale-out .flash-card-animation--right-restore { animation: scale-out-restore-right 0.3s cubic-bezier(0.25,0.46,0.45,0.94) forwards !important; }
.scale-out .flash-card-animation--left-restore { animation: scale-out-restore-left 0.3s cubic-bezier(0.25,0.46,0.45,0.94) forwards !important; }

@keyframes scale-out-right { 0%{opacity:1;} 100%{transform:translateX(300px) scale(0);opacity:0;} }
@keyframes scale-out-left { 0%{opacity:1;} 100%{transform:translateX(-300px) scale(0);opacity:0;} }
@keyframes scale-out-restore-right { 0%{transform:translateX(300px) scale(0);opacity:0;} 100%{transform:translateX(0) scale(1);opacity:1;} }
@keyframes scale-out-restore-left { 0%{transform:translateX(-300px) scale(0);opacity:0;} 100%{transform:translateX(0) scale(1);opacity:1;} }

/* 3D Flip Animation */
.flip-3d .flash-card-animation--right { animation: flip-3d-right 0.5s ease-in-out forwards !important; }
.flip-3d .flash-card-animation--left { animation: flip-3d-left 0.5s ease-in-out forwards !important; }
.flip-3d .flash-card-animation--right-restore { animation: flip-3d-restore-right 0.5s ease-in-out forwards !important; }
.flip-3d .flash-card-animation--left-restore { animation: flip-3d-restore-left 0.5s ease-in-out forwards !important; }

@keyframes flip-3d-right { 0%{opacity:1;} 100%{transform:translateX(300px) rotateY(180deg) rotateX(45deg);opacity:0;} }
@keyframes flip-3d-left { 0%{opacity:1;} 100%{transform:translateX(-300px) rotateY(-180deg) rotateX(45deg);opacity:0;} }
@keyframes flip-3d-restore-right { 0%{transform:translateX(300px) rotateY(180deg) rotateX(45deg);opacity:0;} 100%{transform:translateX(0) rotateY(0deg) rotateX(0deg);opacity:1;} }
@keyframes flip-3d-restore-left { 0%{transform:translateX(-300px) rotateY(-180deg) rotateX(45deg);opacity:0;} 100%{transform:translateX(0) rotateY(0deg) rotateX(0deg);opacity:1;} }

/* Elastic Bounce Animation */
.elastic-bounce .flash-card-animation--right { animation: elastic-bounce-right 0.6s cubic-bezier(0.68,-0.55,0.265,1.55) forwards !important; }
.elastic-bounce .flash-card-animation--left { animation: elastic-bounce-left 0.4s cubic-bezier(0.55,0.055,0.675,0.19) forwards !important; }
.elastic-bounce .flash-card-animation--right-restore { animation: elastic-bounce-restore-right 0.6s cubic-bezier(0.68,-0.55,0.265,1.55) forwards !important; }
.elastic-bounce .flash-card-animation--left-restore { animation: elastic-bounce-restore-left 0.4s cubic-bezier(0.55,0.055,0.675,0.19) forwards !important; }

@keyframes elastic-bounce-right { 0%{opacity:1;} 100%{transform:translateX(300px) scale(1.3) rotate(15deg);opacity:0;} }
@keyframes elastic-bounce-left { 0%{opacity:1;} 100%{transform:translateX(-300px) scale(1.3) rotate(-15deg);opacity:0;} }
@keyframes elastic-bounce-restore-right { 0%{transform:translateX(300px) scale(1.3) rotate(15deg);opacity:0;} 100%{transform:translateX(0) scale(1) rotate(0deg);opacity:1;} }
@keyframes elastic-bounce-restore-left { 0%{transform:translateX(-300px) scale(1.3) rotate(-15deg);opacity:0;} 100%{transform:translateX(0) scale(1) rotate(0deg);opacity:1;} }
</style>
vue
<script setup lang="ts">
interface Card {
  id: number
  title: string
  description: string
  color: string
}

defineProps<{
  card: Card
}>()
</script>

<template>
  <div
    class="card size-full text-white shadow-xl"
    :style="{ backgroundColor: card.color }"
  >
    <div class="card-body">
      <h2 class="card-title">
        {{ card.title }}
      </h2>
      <p>{{ card.description }}</p>
      <div class="card-actions justify-end">
        <div class="badge badge-outline">
          #{{ card.id }}
        </div>
      </div>
    </div>
  </div>
</template>

Key Concepts

  • Transition classes: Apply CSS animations to swiped cards
  • Custom keyframes: Define your own animations
  • Per-direction styles: Different animations for left/right/top/bottom
  • Override default swipe-out animations

Common Patterns

css
/* Fast rotation */
.fast-rotate { animation: fastSpin 0.3s ease-out; }

/* Elastic bounce */
.elastic { animation: elasticBounce 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }

/* 3D flip */
.flip-3d { animation: flip3D 0.6s ease-in-out; }

Released under the MIT License.