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
Strategy, design and code under one roof
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">Strategy, design and code under one roof</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
Stories told in pixels and motion
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">Stories told in pixels and motion</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; }
}3Shapes
Rings, dots, squares and triangles in theme colours float and turn slowly behind the content. Class: fx-bg-shapes
Floating shapes
Brands that stand out and sell
Content stays readable on top of the moving background.
<section class="fx-bg-shapes 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">Floating shapes</p>
<h3 class="h4 fw-bold mb-2">Brands that stand out and sell</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-shapes { position: relative; isolation: isolate; overflow: hidden; }
.fx-bg-shapes::before, .fx-bg-shapes::after { content: ""; position: absolute; pointer-events: none; z-index: -1; }
.fx-bg-shapes::before, .fx-bg-shapes::after { inset: -10%; background-repeat: no-repeat; }
.fx-bg-shapes::before {
background-image:
radial-gradient(circle, transparent 0 38%, rgba(var(--wt-primary-rgb), .35) 40% 50%, transparent 52%),
radial-gradient(circle, rgba(var(--wt-accent-rgb), .35) 0 48%, transparent 50%),
conic-gradient(from 150deg at 50% 0, rgba(var(--wt-secondary-rgb), .3) 0 60deg, transparent 0);
background-size: 90px 90px, 34px 34px, 70px 60px;
background-position: 12% 22%, 82% 18%, 70% 82%;
animation: fx-bg-shapes-float 12s ease-in-out infinite alternate;
}
.fx-bg-shapes::after {
background-image:
linear-gradient(rgba(var(--wt-secondary-rgb), .22), rgba(var(--wt-secondary-rgb), .22)),
radial-gradient(circle, transparent 0 40%, rgba(var(--wt-accent-rgb), .3) 42% 52%, transparent 54%),
radial-gradient(circle, rgba(var(--wt-primary-rgb), .3) 0 48%, transparent 50%);
background-size: 38px 38px, 60px 60px, 22px 22px;
background-position: 88% 62%, 22% 80%, 45% 12%;
animation: fx-bg-shapes-turn 18s ease-in-out infinite alternate;
}
@keyframes fx-bg-shapes-float { to { transform: translate(3%, -5%) rotate(6deg); } }
@keyframes fx-bg-shapes-turn { to { transform: translate(-4%, 4%) rotate(-8deg); } }
@media (prefers-reduced-motion: reduce) {
.fx-bg-shapes, .fx-bg-shapes::before, .fx-bg-shapes::after, .fx-bg-shapes *, .fx-bg-shapes *::before, .fx-bg-shapes *::after { animation: none !important; transition: none !important; }
}