Modern CSS Animations
Keyframe animations for cards, icons, loaders and headings - drop a class on an element and it comes alive.
1Multi-Layer Spinner
A loading indicator made of three counter-rotating rings in the theme colours. Class: fx-multi-layer-spinner
Loading...
Preparing your idea
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<div class="text-center">
<div class="fx-multi-layer-spinner" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<p class="small text-body-secondary mt-3 mb-0">Preparing your idea</p>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-multi-layer-spinner {
position: relative; display: inline-block; width: 4rem; height: 4rem; border-radius: 50%;
border: 4px solid transparent; border-top-color: var(--wt-primary);
animation: fx-multi-layer-spinner-spin 1.1s linear infinite;
}
.fx-multi-layer-spinner::before, .fx-multi-layer-spinner::after { content: ""; position: absolute; border-radius: 50%; border: 4px solid transparent; }
.fx-multi-layer-spinner::before { inset: 4px; border-top-color: var(--wt-secondary); animation: fx-multi-layer-spinner-spin 1.7s linear infinite reverse; }
.fx-multi-layer-spinner::after { inset: 14px; border-top-color: var(--wt-accent); animation: fx-multi-layer-spinner-spin .8s linear infinite; }
@keyframes fx-multi-layer-spinner-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
.fx-multi-layer-spinner, .fx-multi-layer-spinner::before, .fx-multi-layer-spinner::after, .fx-multi-layer-spinner *, .fx-multi-layer-spinner *::before, .fx-multi-layer-spinner *::after { animation: none !important; transition: none !important; }
}2Orbital Motion
Two small planets circle around an avatar, logo or icon on separate orbits. Class: fx-orbital-motion
<div class="d-flex flex-wrap align-items-center justify-content-center gap-3 p-3 h-100" style="min-height:200px">
<div class="fx-orbital-motion">
<img src="../assets/img/avatar-5.svg" alt="Team member avatar" class="rounded-circle shadow" style="width:4.5rem;height:4.5rem">
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-orbital-motion {
position: relative; display: inline-grid; place-items: center; width: 9rem; height: 9rem;
border-radius: 50%; border: 1px dashed rgba(var(--wt-primary-rgb), .45);
}
.fx-orbital-motion::before, .fx-orbital-motion::after {
content: ""; position: absolute; top: 50%; left: 50%; border-radius: 50%; pointer-events: none;
}
.fx-orbital-motion::before {
width: 14px; height: 14px; margin: -7px; background: var(--wt-primary);
box-shadow: 0 0 10px rgba(var(--wt-primary-rgb), .7);
animation: fx-orbital-motion-outer 5s linear infinite;
}
.fx-orbital-motion::after {
width: 10px; height: 10px; margin: -5px; background: var(--wt-accent);
animation: fx-orbital-motion-inner 3.2s linear infinite reverse;
}
@keyframes fx-orbital-motion-outer { from { transform: rotate(0deg) translateX(4.5rem) rotate(0deg); } to { transform: rotate(360deg) translateX(4.5rem) rotate(-360deg); } }
@keyframes fx-orbital-motion-inner { from { transform: rotate(0deg) translateX(3.1rem); } to { transform: rotate(360deg) translateX(3.1rem); } }
@media (prefers-reduced-motion: reduce) {
.fx-orbital-motion, .fx-orbital-motion::before, .fx-orbital-motion::after, .fx-orbital-motion *, .fx-orbital-motion *::before, .fx-orbital-motion *::after { animation: none !important; transition: none !important; }
}3Shimmer Skeleton
Loading placeholders with a light sweep; add the class to every grey block of a skeleton card. Class: fx-shimmer-skeleton
<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 w-100" style="max-width:18rem" aria-busy="true" aria-label="Loading content">
<div class="card-body">
<div class="d-flex align-items-center gap-3 mb-3">
<span class="fx-shimmer-skeleton rounded-circle flex-shrink-0" style="width:48px;height:48px"></span>
<div class="flex-grow-1">
<span class="fx-shimmer-skeleton mb-2" style="width:70%"></span><span class="fx-shimmer-skeleton" style="width:45%"></span>
</div>
</div>
<span class="fx-shimmer-skeleton mb-2" style="height:70px"></span> <span class="fx-shimmer-skeleton mb-2"></span> <span class="fx-shimmer-skeleton" style="width:60%"></span>
</div>
</div>
</div>
/* CSS (already in assets/css/effects.css) */
.fx-shimmer-skeleton {
display: block; min-height: .9rem; border-radius: var(--wt-radius, .5rem);
background: linear-gradient(90deg, rgba(var(--wt-primary-rgb), .08) 25%, rgba(var(--wt-primary-rgb), .22) 37%, rgba(var(--wt-primary-rgb), .08) 63%);
background-size: 400% 100%;
animation: fx-shimmer-skeleton-shine 1.4s ease infinite;
}
@keyframes fx-shimmer-skeleton-shine { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) {
.fx-shimmer-skeleton, .fx-shimmer-skeleton::before, .fx-shimmer-skeleton::after, .fx-shimmer-skeleton *, .fx-shimmer-skeleton *::before, .fx-shimmer-skeleton *::after { animation: none !important; transition: none !important; }
}