Modern CSS Transitions
Polished hover and focus transitions for buttons, cards and links that work on any .btn or .card.
13D Flip Card
Flips a card over in 3D on hover or focus to show its back; use the -inner, -front and -back child classes. Class: fx-3d-flip-card
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<div class="fx-3d-flip-card" style="width:13rem;height:11rem" tabindex="0">
<div class="fx-3d-flip-card-inner">
<div class="fx-3d-flip-card-front shadow-md">
<img src="../assets/img/photo-9.svg" alt="Portrait of Theo Patel" class="w-full h-full object-cover">
</div>
<div class="fx-3d-flip-card-back text-center">
<div class="font-bold">
Theo Patel
</div>
<div class="small opacity-75 mb-2">
Data Analyst
</div>
<a href="#" class="btn btn-light btn-sm">View profile</a>
</div>
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-3d-flip-card { perspective: 1000px; }
.fx-3d-flip-card .fx-3d-flip-card-inner {
position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
transition: transform .7s cubic-bezier(.4, .2, .2, 1);
}
.fx-3d-flip-card:hover .fx-3d-flip-card-inner, .fx-3d-flip-card:focus-within .fx-3d-flip-card-inner { transform: rotateY(180deg); }
.fx-3d-flip-card .fx-3d-flip-card-front, .fx-3d-flip-card .fx-3d-flip-card-back {
position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden;
border-radius: var(--wt-radius-lg, 1rem); overflow: hidden;
}
.fx-3d-flip-card .fx-3d-flip-card-back {
transform: rotateY(180deg); display: flex; flex-direction: column; justify-content: center; padding: 1rem;
color: var(--wt-on-primary, #fff); background: linear-gradient(135deg, var(--wt-primary), var(--wt-secondary));
}
@media (prefers-reduced-motion: reduce) {
.fx-3d-flip-card, .fx-3d-flip-card::before, .fx-3d-flip-card::after, .fx-3d-flip-card *, .fx-3d-flip-card *::before, .fx-3d-flip-card *::after { animation: none !important; transition: none !important; }
}2Magnetic Hover
Fakes a magnetic pull: the element lifts toward the pointer and its icon leans further with an elastic ease. Class: fx-magnetic-hover
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<button type="button" class="btn btn-primary btn-lg rounded-full fx-magnetic-hover"><span>Contact us</span> <span><i class="bi bi-arrow-right" aria-hidden="true"></i></span></button>
<a href="#" class="btn btn-outline-primary rounded-full fx-magnetic-hover" aria-label="Send"><i class="bi bi-send-fill" aria-hidden="true"></i></a>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-magnetic-hover { transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), box-shadow .45s; }
.fx-magnetic-hover > * { display: inline-block; transition: transform .45s cubic-bezier(.34, 1.56, .64, 1); }
.fx-magnetic-hover:hover, .fx-magnetic-hover:focus-visible { transform: translate(3px, -4px) scale(1.06); box-shadow: -6px 12px 22px -10px rgba(var(--wt-primary-rgb), .6); }
.fx-magnetic-hover:hover > *, .fx-magnetic-hover:focus-visible > * { transform: translate(3px, -2px); }
@media (prefers-reduced-motion: reduce) {
.fx-magnetic-hover, .fx-magnetic-hover::before, .fx-magnetic-hover::after, .fx-magnetic-hover *, .fx-magnetic-hover *::before, .fx-magnetic-hover *::after { animation: none !important; transition: none !important; }
}3Rainbow Glow
Surrounds a button or card with a glow that cycles through the theme colours while hovered. Class: fx-rainbow-glow
Pro plan
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<button type="button" class="btn btn-dark btn-lg rounded-full fx-rainbow-glow">Unlock all</button>
<div class="card fx-rainbow-glow" style="width:9rem" tabindex="0">
<div class="card-body text-center py-4">
<div class="text-2xl text-primary">
<i class="bi bi-gem" aria-hidden="true"></i>
</div>
<div class="small font-semibold">
Pro plan
</div>
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-rainbow-glow { transition: box-shadow .4s ease, transform .4s ease; }
.fx-rainbow-glow:hover, .fx-rainbow-glow:focus-visible { transform: translateY(-2px); animation: fx-rainbow-glow-glow 2.4s linear infinite; }
@keyframes fx-rainbow-glow-glow {
0%, 100% { box-shadow: 0 0 14px rgba(var(--wt-primary-rgb), .75), 0 0 34px rgba(var(--wt-primary-rgb), .35); }
33% { box-shadow: 0 0 14px rgba(var(--wt-accent-rgb), .75), 0 0 34px rgba(var(--wt-accent-rgb), .35); }
66% { box-shadow: 0 0 14px rgba(var(--wt-secondary-rgb), .75), 0 0 34px rgba(var(--wt-secondary-rgb), .35); }
}
@media (prefers-reduced-motion: reduce) {
.fx-rainbow-glow, .fx-rainbow-glow::before, .fx-rainbow-glow::after, .fx-rainbow-glow *, .fx-rainbow-glow *::before, .fx-rainbow-glow *::after { animation: none !important; transition: none !important; }
}