Morphing Blob
A pure-CSS organic shape: eight border-radius values morph through an 8-second keyframe cycle with an indigo-to-fuchsia gradient — no script required.
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. Atmosphere has 57 effects, including 10 free. Explore the category →
3 usage examples



How it works
The effect relies entirely on the extended border-radius notation: x1 x2 x3 x4 / y1 y2 y3 y4 sets the horizontal and vertical radii of each corner independently. Four keyframe steps (0%, 25%, 50%, 75%) drive the deformation inside @keyframes morphBlob; the CSS engine interpolates smoothly between them with no imperative code.
The animation uses ease-in-out on the global animation property — not per-step animation-timing-function — which naturally slows each start and end of the cycle and reinforces the impression of a breathing organism rather than a mechanical transition.
The fill is a linear-gradient(135deg, #6366f1, #d946ef) — indigo to fuchsia — drawn diagonally from bottom-left to top-right. The 135° angle accentuates the perception of depth on the ever-shifting silhouette: dark and light corners alternate with each morph.
There is no JavaScript: no requestAnimationFrame, no observer, no script-side state. The animation loop is entirely handled by the browser's rendering engine, guaranteeing optimal GPU performance and seamless integration into any framework.
Accessibility
- No
prefers-reduced-motionin the source code: the animation runs continuously regardless of the system setting. Add to your CSS:@media (prefers-reduced-motion: reduce) { .morph-blob { animation: none; border-radius: 50%; } } - The
.morph-blobis a purely decorative element with no text or interaction — no keyboard focus trap or navigation issue from the effect itself. - The supplied HTML exposes neither
aria-hiddennoraria-label. In decorative use, addaria-hidden="true"on the parent container to exclude the blob from the accessibility tree. - No text contrast to check on the blob alone — contrast responsibility falls on the overlay content placed by the integrator.
- No native events (click, focus, keyboard) attached to the blob: the effect is passive, with no risk of a navigation trap.
Browser compatibility
Requires border-radius with slash notation and CSS animations — supported in all modern browsers since 2012.
If CSS animations are not supported, the <code>div.morph-blob</code> renders as a slightly rounded rectangle with the gradient intact — no JS errors, the page stays readable.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="demo-preview" aria-hidden="true">
<!-- Decorative blob — all mechanics live in CSS -->
<div class="morph-blob"></div>
<!-- Overlay content: position absolute on .demo-preview (position: relative) -->
</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 (.morph-blob, l. 57) | linear-gradient(135deg, #6366f1, #d946ef) | Gradient colors and angle. E.g. linear-gradient(135deg, #0ea5e9, #22d3ee) for an aquatic feel, or a flat color #6366f1 for a monochrome blob. |
| animation-duration (.morph-blob, l. 58) | 8s | Duration of one full morph cycle. 4s = nervous and energetic blob, 16s = slow meditative breathing. |
| width / height (.morph-blob, l. 55-56) | 200px | Shape size. Equal values = near-square blob; higher height = vertically elongated blob. |
| animation-timing-function (.morph-blob, l. 58) | ease-in-out | Timing curve. linear = constant mechanical morphing, ease-in-out = slowdown at extremes (organic feel). |
| border-radius 0%/100% (@keyframes, l. 32) | 60% 40% 30% 70%/60% 30% 70% 40% | Start and end shape (0% and 100% of the cycle). Any combination of 0 to 100% is valid for all 8 values. |
| border-radius 50% (@keyframes, l. 40) | 50% 60% 30%/30% 40% 70% 50% | Mid-cycle shape. Changing these values alters the intermediate point furthest from the initial silhouette. |
FAQ
@keyframes morphBlob and applied via animation on .morph-blob. Compatible with Angular, React, Vue, and Svelte — just include the CSS and place <div class="morph-blob"></div> in the DOM.prefers-reduced-motion. Add to your CSS: @media (prefers-reduced-motion: reduce) { .morph-blob { animation: none; border-radius: 50%; } } — the blob becomes a static circle with the gradient intact.filter: hue-rotate() on .morph-blob with a second @keyframes, which rotates the gradient's hues across the spectrum without touching the effect's structure.