Modern CSS Transitions
Polished hover and focus transitions for buttons, cards and links that work on any .btn or .card.
1Neon Fill Button
An outline button that fills with colour from the left and glows; works on any .btn or link. Class: fx-neon-fill-button
<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-neon-fill-button">Join now</button>
<a href="#" class="btn fx-neon-fill-button rounded-pill">Learn more <i class="bi bi-arrow-right" aria-hidden="true"></i></a>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-neon-fill-button, .btn.fx-neon-fill-button {
position: relative; isolation: isolate; overflow: hidden; z-index: 0;
color: var(--wt-primary-ink); background: transparent; border: 2px solid var(--wt-primary);
transition: color .35s ease, box-shadow .35s ease;
}
.fx-neon-fill-button::before {
content: ""; position: absolute; inset: 0; z-index: -1; background: var(--wt-primary);
transform: scaleX(0); transform-origin: left center; transition: transform .4s cubic-bezier(.7, 0, .3, 1);
}
.fx-neon-fill-button:hover, .fx-neon-fill-button:focus-visible, .btn.fx-neon-fill-button:hover, .btn.fx-neon-fill-button:focus-visible {
color: var(--wt-on-primary, #fff); border-color: var(--wt-primary);
box-shadow: 0 0 12px rgba(var(--wt-primary-rgb), .6), 0 0 32px rgba(var(--wt-primary-rgb), .35);
}
.fx-neon-fill-button:hover::before, .fx-neon-fill-button:focus-visible::before { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
.fx-neon-fill-button, .fx-neon-fill-button::before, .fx-neon-fill-button::after, .fx-neon-fill-button *, .fx-neon-fill-button *::before, .fx-neon-fill-button *::after { animation: none !important; transition: none !important; }
}2Rainbow 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; }
}3Elastic Scale
Buttons, chips and cards that grow with a rubbery overshoot on hover and squash when pressed. Class: fx-elastic-scale
<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-primary fx-elastic-scale">Continue</button>
<span class="badge rounded-pill text-bg-secondary fs-6 fx-elastic-scale">tips</span> <a href="#" class="btn btn-outline-primary rounded-circle fs-5 fx-elastic-scale" aria-label="Cart, $45.28"><i class="bi bi-cart3" aria-hidden="true"></i></a>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-elastic-scale { transition: transform .5s cubic-bezier(.34, 1.56, .64, 1); }
.fx-elastic-scale:hover, .fx-elastic-scale:focus-visible { transform: scale(1.08); }
.fx-elastic-scale:active { transform: scale(.94); transition-duration: .15s; }
@media (prefers-reduced-motion: reduce) {
.fx-elastic-scale, .fx-elastic-scale::before, .fx-elastic-scale::after, .fx-elastic-scale *, .fx-elastic-scale *::before, .fx-elastic-scale *::after { animation: none !important; transition: none !important; }
}