Keyframe animations for cards, icons, loaders and headings - drop a class on an element and it comes alive.
1Pulse Wave Effect
Sends expanding rings out of a button, avatar or status dot to draw the eye. Class: fx-pulse-wave-effect
Liam Brennan
Live now<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 rounded-circle d-inline-flex align-items-center justify-content-center fs-4 fx-pulse-wave-effect" style="width:4rem;height:4rem" aria-label="Start live session"><i class="bi bi-broadcast" aria-hidden="true"></i></button>
<div class="d-flex align-items-center gap-2">
<img src="../assets/img/avatar-2.svg" alt="Portrait of the host" class="rounded-circle fx-pulse-wave-effect" width="48" height="48">
<div>
<div class="fw-semibold small">
Liam Brennan
</div>
<span class="badge text-bg-success">Live now</span>
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-pulse-wave-effect { animation: fx-pulse-wave-effect-pulse 2s ease-out infinite; }
@keyframes fx-pulse-wave-effect-pulse {
0% { box-shadow: 0 0 0 0 rgba(var(--wt-primary-rgb), .55), 0 0 0 0 rgba(var(--wt-primary-rgb), .35); }
70% { box-shadow: 0 0 0 16px rgba(var(--wt-primary-rgb), 0), 0 0 0 32px rgba(var(--wt-primary-rgb), 0); }
100% { box-shadow: 0 0 0 0 rgba(var(--wt-primary-rgb), 0), 0 0 0 0 rgba(var(--wt-primary-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
.fx-pulse-wave-effect, .fx-pulse-wave-effect::before, .fx-pulse-wave-effect::after, .fx-pulse-wave-effect *, .fx-pulse-wave-effect *::before, .fx-pulse-wave-effect *::after { animation: none !important; transition: none !important; }
}2Bouncing Text
Makes each letter of a short word hop in turn; wrap every letter in a span with --i set to its index. Class: fx-bouncing-text
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<h2 class="display-5 fw-bold mb-0 fx-bouncing-text" aria-label="Yay!"><span style="--i:0" aria-hidden="true">Y</span><span style="--i:1" aria-hidden="true">a</span><span style="--i:2" aria-hidden="true">y</span><span style="--i:3" aria-hidden="true">!</span></h2>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-bouncing-text { display: inline-flex; }
.fx-bouncing-text > span {
display: inline-block;
animation: fx-bouncing-text-bounce 1.6s ease-in-out infinite;
animation-delay: calc(var(--i, 0) * .09s);
}
@keyframes fx-bouncing-text-bounce {
0%, 60%, 100% { transform: translateY(0); }
25% { transform: translateY(-14px); color: var(--wt-primary-ink); }
40% { transform: translateY(2px); }
}
@media (prefers-reduced-motion: reduce) {
.fx-bouncing-text, .fx-bouncing-text::before, .fx-bouncing-text::after, .fx-bouncing-text *, .fx-bouncing-text *::before, .fx-bouncing-text *::after { animation: none !important; transition: none !important; }
}