Advanced Animated Backgrounds
Animated section backgrounds that sit behind your content and work on light and dark sections alike.
1Particles
Two layers of tiny glowing dots drifting upward at different speeds, like dust in light. Class: fx-bg-particles
Particles
Big ideas, small rooms, real conversations
Content stays readable on top of the moving background.
<section class="fx-bg-particles bg-dark text-white rounded-4 p-4 text-center d-flex flex-column justify-content-center" style="min-height:210px">
<p class="small text-uppercase fw-semibold mb-1 text-white-50">Particles</p>
<h3 class="h4 fw-bold mb-2">Big ideas, small rooms, real conversations</h3>
<p class="small mb-3 text-white-50">Content stays readable on top of the moving background.</p>
<div>
<a href="#" class="btn btn-primary btn-sm">Get started</a>
</div>
</section>
/* CSS (already in assets/css/effects.css) */
.fx-bg-particles { position: relative; isolation: isolate; overflow: hidden; }
.fx-bg-particles::before, .fx-bg-particles::after { content: ""; position: absolute; pointer-events: none; z-index: -1; }
.fx-bg-particles::before, .fx-bg-particles::after { inset: 0; }
.fx-bg-particles::before {
background-image:
radial-gradient(circle at 10% 20%, rgba(var(--wt-primary-rgb), .65) 0 2px, transparent 3px),
radial-gradient(circle at 35% 70%, rgba(var(--wt-accent-rgb), .6) 0 1.5px, transparent 2.5px),
radial-gradient(circle at 60% 35%, rgba(var(--wt-secondary-rgb), .55) 0 2px, transparent 3px),
radial-gradient(circle at 85% 80%, rgba(var(--wt-primary-rgb), .5) 0 1.5px, transparent 2.5px);
background-size: 180px 180px;
animation: fx-bg-particles-near 14s linear infinite;
}
.fx-bg-particles::after {
opacity: .7;
background-image:
radial-gradient(circle at 20% 55%, rgba(var(--wt-accent-rgb), .55) 0 3px, transparent 4px),
radial-gradient(circle at 70% 15%, rgba(var(--wt-primary-rgb), .45) 0 3.5px, transparent 4.5px),
radial-gradient(circle at 50% 90%, rgba(var(--wt-secondary-rgb), .4) 0 2.5px, transparent 3.5px);
background-size: 300px 300px;
animation: fx-bg-particles-far 30s linear infinite;
}
@keyframes fx-bg-particles-near { to { background-position: 0 -180px; } }
@keyframes fx-bg-particles-far { to { background-position: 0 -300px; } }
@media (prefers-reduced-motion: reduce) {
.fx-bg-particles, .fx-bg-particles::before, .fx-bg-particles::after, .fx-bg-particles *, .fx-bg-particles *::before, .fx-bg-particles *::after { animation: none !important; transition: none !important; }
}2Wave/Blob
Soft colour blobs morph in the background while two layers of waves roll along the bottom edge. Class: fx-bg-wave-blob
Wave and blob
Learn from the best, meet the rest
Content stays readable on top of the moving background.
<section class="fx-bg-wave-blob bg-body border rounded-4 p-4 text-center d-flex flex-column justify-content-center" style="min-height:210px">
<p class="small text-uppercase fw-semibold mb-1 text-body-secondary">Wave and blob</p>
<h3 class="h4 fw-bold mb-2">Learn from the best, meet the rest</h3>
<p class="small mb-3 text-body-secondary">Content stays readable on top of the moving background.</p>
<div>
<a href="#" class="btn btn-primary btn-sm">Get started</a>
</div>
</section>
/* CSS (already in assets/css/effects.css) */
.fx-bg-wave-blob { position: relative; isolation: isolate; overflow: hidden; }
.fx-bg-wave-blob::before, .fx-bg-wave-blob::after { content: ""; position: absolute; pointer-events: none; z-index: -1; }
.fx-bg-wave-blob::before {
width: 55%; aspect-ratio: 1; top: -25%; left: -12%;
background: radial-gradient(circle at 50% 50%, rgba(var(--wt-primary-rgb), .32), transparent 68%);
border-radius: 42% 58% 63% 37% / 41% 44% 56% 59%;
animation: fx-bg-wave-blob-blob 14s ease-in-out infinite alternate;
}
.fx-bg-wave-blob::after {
left: 0; right: 0; bottom: 0; height: 60px;
background:
radial-gradient(84px 18px at 50% 100%, rgba(var(--wt-primary-rgb), .2) 99%, transparent 101%) 0 100% / 160px 30px repeat-x,
radial-gradient(118px 24px at 50% 100%, rgba(var(--wt-accent-rgb), .18) 99%, transparent 101%) 0 100% / 220px 40px repeat-x,
linear-gradient(rgba(var(--wt-primary-rgb), .14), rgba(var(--wt-primary-rgb), .14)) 0 100% / 100% 12px no-repeat;
animation: fx-bg-wave-blob-wave 9s linear infinite;
}
@keyframes fx-bg-wave-blob-blob {
0% { transform: translate(0, 0) rotate(0deg); border-radius: 42% 58% 63% 37% / 41% 44% 56% 59%; }
50% { border-radius: 70% 30% 46% 54% / 30% 39% 61% 70%; }
100% { transform: translate(110%, 35%) rotate(60deg); border-radius: 30% 70% 70% 30% / 53% 30% 70% 47%; }
}
@keyframes fx-bg-wave-blob-wave { to { background-position: 160px 100%, -220px 100%, 0 100%; } }
@media (prefers-reduced-motion: reduce) {
.fx-bg-wave-blob, .fx-bg-wave-blob::before, .fx-bg-wave-blob::after, .fx-bg-wave-blob *, .fx-bg-wave-blob *::before, .fx-bg-wave-blob *::after { animation: none !important; transition: none !important; }
}