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="https://images.unsplash.com/photo-1578894381163-e72c17f2d45f?auto=format&fit=crop&w=1200&h=800&q=70" alt="Portrait of Elena Brennan" class="w-full h-full object-cover">
</div>
<div class="fx-3d-flip-card-back text-center">
<div class="font-bold">
Elena Brennan
</div>
<div class="small opacity-75 mb-2">
Product Designer
</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; }
}2Liquid Ripple
A button that fills with a swirling liquid from the bottom on hover. Class: fx-liquid-ripple
<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-lg px-6 fx-liquid-ripple">Order now</button>
<button type="button" class="btn rounded-full fx-liquid-ripple">Hover me</button>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-liquid-ripple, .btn.fx-liquid-ripple {
position: relative; isolation: isolate; overflow: hidden; z-index: 0;
color: var(--wt-primary-ink); background: var(--wt-surface, #fff); border: 2px solid var(--wt-primary);
transition: color .5s ease;
}
.fx-liquid-ripple::before {
content: ""; position: absolute; z-index: -1; left: 50%; top: 100%; width: 240%; aspect-ratio: 1;
margin-left: -120%; margin-top: 12%; border-radius: 42%;
background: var(--wt-primary);
transition: top .8s ease, margin-top .8s ease;
animation: fx-liquid-ripple-swirl 5s linear infinite;
}
.fx-liquid-ripple:hover, .fx-liquid-ripple:focus-visible, .btn.fx-liquid-ripple:hover, .btn.fx-liquid-ripple:focus-visible { color: var(--wt-on-primary, #fff); border-color: var(--wt-primary); }
.fx-liquid-ripple:hover::before, .fx-liquid-ripple:focus-visible::before { top: 50%; margin-top: -120%; }
.fx-liquid-ripple:active { transform: scale(.97); }
@keyframes fx-liquid-ripple-swirl { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
.fx-liquid-ripple, .fx-liquid-ripple::before, .fx-liquid-ripple::after, .fx-liquid-ripple *, .fx-liquid-ripple *::before, .fx-liquid-ripple *::after { animation: none !important; transition: none !important; }
}3Magnetic 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>Say hello</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; }
}