Polished hover and focus transitions for buttons, cards and links that work on any .btn or .card.
1Morphing Gradient
A gradient button that softly changes to a second gradient and morphs into a pill on hover. Class: fx-morphing-gradient
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<button type="button" class="btn btn-lg fx-morphing-gradient">Start free trial</button>
<button type="button" class="btn fx-morphing-gradient"><i class="bi bi-download" aria-hidden="true"></i> Download</button>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-morphing-gradient, .btn.fx-morphing-gradient {
position: relative; isolation: isolate; overflow: hidden; z-index: 0; border: 0;
color: var(--wt-on-primary, #fff); border-radius: .6rem;
background: linear-gradient(135deg, var(--wt-primary), var(--wt-secondary));
transition: border-radius .5s ease, transform .5s ease, box-shadow .5s;
}
.fx-morphing-gradient::before {
content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0;
background: linear-gradient(135deg, var(--wt-accent), var(--wt-primary));
transition: opacity .5s ease;
}
.fx-morphing-gradient:hover, .fx-morphing-gradient:focus-visible, .btn.fx-morphing-gradient:hover, .btn.fx-morphing-gradient:focus-visible {
color: var(--wt-on-primary, #fff); border-radius: 2rem; transform: translateY(-2px);
box-shadow: 0 12px 24px -10px rgba(var(--wt-accent-rgb), .7);
}
.fx-morphing-gradient:hover::before, .fx-morphing-gradient:focus-visible::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
.fx-morphing-gradient, .fx-morphing-gradient::before, .fx-morphing-gradient::after, .fx-morphing-gradient *, .fx-morphing-gradient *::before, .fx-morphing-gradient *::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="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<button type="button" class="btn btn-lg px-4 fx-liquid-ripple">Subscribe</button>
<button type="button" class="btn rounded-pill 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; }
}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="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<button type="button" class="btn btn-dark btn-lg rounded-pill fx-rainbow-glow">Get the bundle</button>
<div class="card fx-rainbow-glow" style="width:9rem" tabindex="0">
<div class="card-body text-center py-3">
<div class="fs-3 text-primary">
<i class="bi bi-gem" aria-hidden="true"></i>
</div>
<div class="small fw-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; }
}