Modern CSS Animations
Keyframe animations for cards, icons, loaders and headings - drop a class on an element and it comes alive.
1Floating Animation
Lets any card, icon or image drift gently up and down as if it were weightless. Class: fx-floating-animation
Tax receipts
Hover to pause
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<div class="card border-0 shadow text-center fx-floating-animation" style="width:12rem">
<div class="card-body">
<div class="fs-1 text-primary mb-2">
<i class="bi bi-rocket-takeoff-fill" aria-hidden="true"></i>
</div>
<h3 class="h6 mb-1">Tax receipts</h3>
<p class="small text-body-secondary mb-0">Hover to pause</p>
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-floating-animation { animation: fx-floating-animation-float 3.6s ease-in-out infinite; will-change: transform; }
.fx-floating-animation:hover { animation-play-state: paused; }
@keyframes fx-floating-animation-float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
@media (prefers-reduced-motion: reduce) {
.fx-floating-animation, .fx-floating-animation::before, .fx-floating-animation::after, .fx-floating-animation *, .fx-floating-animation *::before, .fx-floating-animation *::after { animation: none !important; transition: none !important; }
}2Typewriter
Types a single line of monospace text letter by letter with a blinking caret; set --fx-ch to the character count. Class: fx-typewriter
terminal
Deploy complete<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<div class="bg-dark text-white rounded-3 p-3 w-100" style="max-width:18rem">
<div class="small text-white-50 mb-1">
terminal
</div>
<span class="fx-typewriter" style="--fx-ch:15">Deploy complete</span>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-typewriter {
display: inline-block; max-width: 100%; overflow: hidden; white-space: nowrap; vertical-align: bottom;
font-family: var(--ui-font-monospace, monospace);
width: calc(var(--fx-ch, 20) * 1ch + .15em);
border-right: .12em solid var(--wt-primary);
animation: fx-typewriter-type 4.5s steps(var(--fx-ch, 20)) infinite, fx-typewriter-caret .8s step-end infinite;
}
@keyframes fx-typewriter-type { 0% { width: 0; } 65%, 100% { width: calc(var(--fx-ch, 20) * 1ch + .15em); } }
@keyframes fx-typewriter-caret { 50% { border-color: transparent; } }
@media (prefers-reduced-motion: reduce) {
.fx-typewriter, .fx-typewriter::before, .fx-typewriter::after, .fx-typewriter *, .fx-typewriter *::before, .fx-typewriter *::after { animation: none !important; transition: none !important; }
}3Heartbeat
A double-beat pulse for like buttons, favourite icons and notification badges. Class: fx-heartbeat
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<span class="display-4 text-danger fx-heartbeat"><i class="bi bi-heart-fill" aria-hidden="true"></i></span>
<button type="button" class="btn btn-outline-danger rounded-pill"><span class="fx-heartbeat"><i class="bi bi-heart-fill" aria-hidden="true"></i></span> 271 likes</button>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-heartbeat { display: inline-block; animation: fx-heartbeat-beat 1.5s ease-in-out infinite; transform-origin: center; }
@keyframes fx-heartbeat-beat {
0%, 40%, 100% { transform: scale(1); }
12% { transform: scale(1.2); }
24% { transform: scale(.96); }
32% { transform: scale(1.14); }
}
@media (prefers-reduced-motion: reduce) {
.fx-heartbeat, .fx-heartbeat::before, .fx-heartbeat::after, .fx-heartbeat *, .fx-heartbeat *::before, .fx-heartbeat *::after { animation: none !important; transition: none !important; }
}