Animated Blobs
Three pure-CSS organic shapes float gently using blur(80px) and desynchronised keyframes — an animated background with zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Backgrounds has 50 effects, including 6 free. Explore the category →
3 usage examples



How it works
The effect is entirely CSS-driven: each .blob is a round <div> (border-radius: 50%) given a filter: blur(80px) that diffuses its color well beyond its actual dimensions. This gaussian spread turns a plain colored circle into an organic shape with undefined edges — no SVG, no library.
Two distinct @keyframes rules orchestrate the movement: blobMove for blob-1 and blob-2 (absolutely positioned at the container corners) applies direct translations (translate(50px, -50px) at peak) combined with scale variations (0.9–1.1). blobMoveCenter — reserved for blob-3, centered via top: 50%; left: 50% — preserves the translate(-50%, -50%) offset at every keyframe using calc() offsets, so the shape stays anchored around the geometric center even as it drifts.
All three blobs cycle over 20 s with staggered negative delays: -7 s for blob-2 (via animation-delay), -14 s for blob-3 (embedded in the animation shorthand). They never synchronise, producing a continuous and natural dance. overflow: hidden on .bg-blob clips the overflow — blob-1 (top: -100px; left: -100px) and blob-2 (bottom: -100px; right: -100px) start outside the container and emerge gradually from the edges, enhancing perceived depth.
The shared opacity: 0.6 generates partial additivity in overlapping zones: indigo (#6366f1), fuchsia (#d946ef), and cyan (#06b6d4) blend into intermediate hues with no custom blend mode. Being zero-JavaScript, there is no requestAnimationFrame or pause logic — CSS animations are handled directly by the browser's compositing engine, GPU-accelerated.
Accessibility
- No prefers-reduced-motion in the code: the CSS has no
@media (prefers-reduced-motion)block — animations run continuously even for users who have enabled this OS preference. Add it if the effect covers a large area or runs for extended periods:@media (prefers-reduced-motion: reduce) { .blob { animation: none; } }. - No ARIA attributes on
.bg-blobor its children — if the background conveys meaningful visual information, addrole="img"andaria-labelto the container. - The
<span class="bg-label">in the demo HTML is read by screen readers as-is — remove it or addaria-hidden="true"if it is a demo-only label irrelevant to end users. - Overlay content contrast: blobs shift position continuously, so light and dark zones change over time. If you place text on top, test multiple configurations and add a semi-transparent scrim to guarantee WCAG AA (ratio ≥ 4.5:1).
- Keyboard navigation: the effect is purely decorative with no scripted interaction — fully compatible with any tab order, no focus trap.
Browser compatibility
Requires CSS animations and filter: blur() — supported in all modern browsers since 2016. Zero external dependencies.
If <code>filter: blur()</code> is unsupported (browsers before 2016), blobs render as solid colored circles — the organic look disappears but the page stays functional with no JS errors.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="bg-blob">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<!-- Your content on top -->
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| background in .blob-1 | #6366f1 | Color of the main shape (indigo, top-left corner). Replace with any valid CSS value: hex, hsl, oklch. |
| background in .blob-2 | #d946ef | Color of the secondary shape (fuchsia, bottom-right corner), animated with a -7 s delay. |
| background in .blob-3 | #06b6d4 | Color of the central shape (cyan), driven by blobMoveCenter to stay anchored at the container center. |
| filter: blur(80px) in .blob | 80px | Diffusion intensity. 40–60 px = sharper edges, 100–120 px = nearly dissolved. Higher values are heavier on GPU. |
| opacity: .6 in .blob | 0.6 | Transparency shared by all shapes. 0.3 = very subtle, 0.8 = saturated colors. Also controls how colors blend at intersections. |
| width/height in .blob-1/.blob-2/.blob-3 | 300 px / 250 px / 200 px | Size of each shape. Rule of thumb: blob ≈ 50–80% of the container's shortest dimension. |
| 20s in animation (all three blobs) | 20s | Duration of one full cycle. 12 s = fast and energetic, 30 s = slow and cinematic. Use the same value for all three blobs to maintain rhythmic coherence. |
| background: #0a0a0f in .bg-blob | #0a0a0f | Background color. Switch to a light value (e.g. #f8fafc) and lower blob opacity to 0.3–0.4 for a pastel look. |
FAQ
background: #0a0a0f in .bg-blob to a light color (e.g. #f0f4f8) and lower blob opacity to 0.3–0.4. The default colors (#6366f1 indigo, #d946ef fuchsia) work well on white — adjust to match your palette.<div class="blob blob-4"></div> to the HTML. In CSS: .blob-4 { width: 220px; height: 220px; background: #f97316; top: 20%; right: -80px; animation-delay: -10s; } — reuse the existing blobMove animation, no third keyframe rule needed.filter: blur() is GPU-accelerated but can be costly on large surfaces or with many blobs. On low-end mobile, reduce blur to 50–60 px and shrink blob sizes. To respect accessibility preferences, add @media (prefers-reduced-motion: reduce) { .blob { animation: none; } }.