Modern CSS Transitions
Polished hover and focus transitions for buttons, cards and links that work on any .btn or .card.
1Glassmorphism Hover
A frosted-glass card that turns clearer, brighter and lifts when hovered; place it over a colourful background. Class: fx-glassmorphism-hover
Mateo Moreau
Data Analyst
Frosted glass that clears on hover.
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full rounded-xl" style="min-height:200px;background:radial-gradient(circle at 20% 25%, var(--wt-accent) 0 18%, transparent 19%),radial-gradient(circle at 82% 75%, var(--wt-secondary) 0 22%, transparent 23%),linear-gradient(135deg, var(--wt-primary), var(--wt-secondary))">
<div class="fx-glassmorphism-hover rounded-xl p-4" style="width:14rem">
<div class="flex items-center gap-2 mb-2">
<img src="../assets/img/avatar-6.svg" alt="Member avatar" class="rounded-full" style="width:40px;height:40px">
<div>
<div class="font-semibold small">
Mateo Moreau
</div>
<div class="small opacity-75">
Data Analyst
</div>
</div>
</div>
<p class="small mb-0">Frosted glass that clears on hover.</p>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-glassmorphism-hover {
color: #fff; background: rgba(255, 255, 255, .14); border: 1px solid rgba(255, 255, 255, .28);
-webkit-backdrop-filter: blur(8px) saturate(140%); backdrop-filter: blur(8px) saturate(140%);
box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
transition: background .45s, backdrop-filter .45s, transform .45s cubic-bezier(.2, .8, .2, 1), box-shadow .45s, border-color .45s;
}
.fx-glassmorphism-hover:hover, .fx-glassmorphism-hover:focus-within {
background: rgba(255, 255, 255, .24); border-color: rgba(255, 255, 255, .55);
-webkit-backdrop-filter: blur(16px) saturate(180%); backdrop-filter: blur(16px) saturate(180%);
transform: translateY(-5px); box-shadow: 0 18px 40px rgba(0, 0, 0, .2);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
.fx-glassmorphism-hover { background: rgba(var(--wt-primary-rgb), .82); }
}
@media (prefers-reduced-motion: reduce) {
.fx-glassmorphism-hover, .fx-glassmorphism-hover::before, .fx-glassmorphism-hover::after, .fx-glassmorphism-hover *, .fx-glassmorphism-hover *::before, .fx-glassmorphism-hover *::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>Let's talk</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; }
}3Split Text Fill
Fills a heading or link with the primary colour from both sides at once on hover - top half from the left, bottom half from the right. Class: fx-split-text-fill
<div class="flex flex-wrap items-center justify-center gap-4 p-4 h-full" style="min-height:200px">
<a href="#" class="display-6 font-bold fx-split-text-fill">Hover this title</a>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-split-text-fill {
display: inline-block; text-decoration: none;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(var(--wt-primary), var(--wt-primary)), linear-gradient(var(--wt-primary), var(--wt-primary)), linear-gradient(currentColor, currentColor);
background-repeat: no-repeat;
background-position: 0 0, 100% 100%, 0 0;
background-size: 0% 50%, 0% 50%, 100% 100%;
-webkit-background-clip: text; background-clip: text;
transition: background-size .6s cubic-bezier(.7, 0, .3, 1);
}
.fx-split-text-fill:hover, .fx-split-text-fill:focus-visible { background-size: 100% 50%, 100% 50%, 100% 100%; }
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
.fx-split-text-fill { -webkit-text-fill-color: currentColor; background: none; }
.fx-split-text-fill:hover { color: var(--wt-primary-ink); }
}
@media (prefers-reduced-motion: reduce) {
.fx-split-text-fill, .fx-split-text-fill::before, .fx-split-text-fill::after, .fx-split-text-fill *, .fx-split-text-fill *::before, .fx-split-text-fill *::after { animation: none !important; transition: none !important; }
}