How to svg blob animation techniques: morphing, pulse, and drift
- Step 1Generate both keyframe shapes at the same Points value — In the Blob Generator, set Points (say 6) and Color, then click Generate twice, copying each
dvalue. Both paths will have the same number ofCcommands — the precondition for clean CSS morphing. Do this in one session: there is no seed, so you cannot recreate a shape later. - Step 2CSS d-property morphing (no JavaScript) — Put both
dvalues in a keyframe:@keyframes blob { 0%,100% { d: path('M…A'); } 50% { d: path('M…B'); } }and applyanimation: blob 8s ease-in-out infiniteto the<path>. The animated CSSdproperty has solid modern-browser support; it requires same-command-count paths, which same-Points blobs satisfy. - Step 3Step up to GSAP MorphSVG for mismatched shapes — If your two shapes have different point counts (or you morph blob → circle), use GSAP's MorphSVG plugin:
gsap.to('#blob', { duration: 4, morphSVG: '#target', repeat: -1, yoyo: true, ease: 'sine.inOut' }). It subdivides the simpler path to match the more complex one before interpolating. - Step 4Fake drift with transforms — no morphing needed — For a 'floating' blob, animate
transforminstead of the path:@keyframes float { 0%,100% { transform: translateY(0) rotate(0); } 50% { transform: translateY(-20px) rotate(5deg); } }. Rotation on an asymmetric blob reads as organic drift and stays on the compositor (cheap). - Step 5Animate colour and softness in CSS — The generator has no gradient or opacity, so animate those externally: transition
fillbetween two colours, or pulseopacity/filter: blur()on the element. Keep shape-morph and colour-morph as separate concerns for control. - Step 6Gate everything behind prefers-reduced-motion — Wrap the animations:
@media (prefers-reduced-motion: reduce) { .blob { animation: none; transition: none; } }. The blob stays on screen as a static shape — do not remove it, or the layout may shift.
Blob animation techniques compared
Pick the lightest technique that meets the requirement. 'Same point count' refers to two blobs generated at the same Points value in the JAD generator.
| Technique | Needs JS? | Handles different point counts? | Best for |
|---|---|---|---|
CSS d property keyframes | No | No — requires same command count | Two same-Points blobs breathing between two shapes |
CSS transform (translate/rotate/scale) | No | N/A — no morphing | Floating / drifting blobs, cheap and compositor-friendly |
| GSAP MorphSVG | Yes | Yes — subdivides to match | Blob → circle/rect, or mismatched point counts |
| Flubber.js | Yes | Yes — interpolates any two shapes | React/D3 pipelines, open-source projects |
Why same-Points blobs morph cleanly
The generator emits one closed <path> whose command count is fixed by the Points value. Matching counts is the whole game for CSS morphing.
| Generator setting | Path commands emitted | CSS d-morph against another blob? |
|---|---|---|
| Both blobs at Points 6 | M + 5×C + Z (same on both) | Yes — clean interpolation |
| Both blobs at Points 8 | M + 7×C + Z (same on both) | Yes — clean interpolation |
| One at 6, one at 8 | 6 vs 8 commands (mismatched) | No — use GSAP/Flubber instead |
Cookbook
Copy-paste recipes for each technique, plus the one accessibility block every animated blob should ship with. The blob markup comes from the JAD generator; the animation is yours.
Zero-JS breathing blob (CSS d property)
Two blobs at the same Points value. Drop both d values into keyframes. Works in modern browsers that support the animatable CSS d property.
@keyframes blob-breathe {
0%, 100% { d: path('M243,93 C… Z'); } /* blob A, Points 6 */
50% { d: path('M251,88 C… Z'); } /* blob B, Points 6 */
}
.blob path {
animation: blob-breathe 9s ease-in-out infinite;
}Floating blob with transforms (no morph)
Cheapest organic motion: move and rotate the whole SVG. Rotation on an asymmetric blob makes the silhouette appear to drift.
@keyframes float {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-24px) rotate(6deg); }
}
.blob {
animation: float 7s ease-in-out infinite;
will-change: transform;
}GSAP MorphSVG between two shapes
Use when the shapes have different point counts, or to morph a blob into a non-blob. MorphSVG matches command counts for you.
gsap.registerPlugin(MorphSVGPlugin);
gsap.to('#blob', {
duration: 4,
morphSVG: '#blob-target',
ease: 'sine.inOut',
repeat: -1,
yoyo: true
});Animate the fill the generator cannot
The export has a solid fill only. Transition fill in CSS for a colour-shift effect, or layer it with the shape morph.
@keyframes hue {
0%,100% { fill: #6366f1; }
50% { fill: #ec4899; }
}
.blob path {
animation: hue 10s linear infinite;
}
/* For a gradient morph, add a <linearGradient> in <defs>
and animate its stop-color instead. */Respect prefers-reduced-motion
Ship this with every animated blob. The shape stays visible; only the motion stops.
@media (prefers-reduced-motion: reduce) {
.blob,
.blob path {
animation: none !important;
transition: none !important;
}
}Edge cases and what actually happens
Morphing blobs with different point counts in plain CSS
invalid morphThe CSS d property interpolates command-by-command. Two blobs from different Points values have different command counts, so the browser cannot pair them — you get jumpy or broken intermediate frames. Generate both shapes at the same Points value, or switch to GSAP/Flubber which subdivide to match.
Trying to reproduce a shape you closed the tab on
failThere is no seed in the generator, so you cannot recreate a previous random blob from its settings. Always copy or save both keyframe shapes before leaving the page — losing one means re-art-directing the whole animation.
Expecting the generator to output the gradient or opacity you animate
By designThe export is a single solid-fill <path> with no fill-opacity and no <defs>. Colour shifts and soft pulses are CSS you add to the element or path — animate fill, opacity, or filter yourself; do not expect them in the copied SVG.
CSS d property not animating in an older browser
unsupportedAnimating the CSS d property needs a reasonably modern engine. In an environment that does not support it, the path snaps to the last keyframe instead of tweening. Provide a transform-based drift fallback (which is universally supported) or use GSAP, which animates the attribute via JS.
Morphing causes layout reflow
PreservedChanging the path d does not trigger layout as long as the SVG element's box size is fixed (the generator's width/height are fixed at 400). Animate transform/opacity for movement — never width, height, top, or left — to stay on the compositor.
Morphing a blob into a circle
SupportedConvert the circle to a path and let GSAP MorphSVG or Flubber distribute points along both outlines. The plain CSS d property cannot do this reliably because a circle path and a blob path rarely share a command structure.
Animation ignores reduced-motion preference
accessibility failContinuous morphing or drifting can cause discomfort for motion-sensitive users. Always wrap blob animation in @media (prefers-reduced-motion: reduce) and disable it. Keep the static blob — removing it can shift surrounding layout.
Smoothing differences between the two blobs
ExpectedSmoothing is fixed at 0.4 in the web UI, so two web-generated blobs share the same tension — good for morphing. If you generate via the API with different blobSmoothing values, the curve character differs and the morph mid-frames look uneven even at the same point count. Keep smoothing constant across a morph pair.
Many high-point blobs animating at once
performance riskEach C command is a tween target. A page full of Points-10 blobs all morphing simultaneously multiplies the per-frame work. Limit concurrent morphs, prefer transform-drift for background blobs, and test on a mid-range phone — not a flagship.
Hand-editing the path so counts no longer match
invalid morphIf you manually add or remove a C segment in one of the two shapes (e.g. while tweaking it), the command counts diverge and CSS morphing breaks. Either keep both paths byte-structurally parallel or move to a library-based morph.
Frequently asked questions
Why do my two blobs morph badly with CSS?
Almost always a command-count mismatch. The CSS d property pairs commands positionally, so both paths must have the same number and type of commands. Generate both blobs at the same Points value (same number of C segments) and the morph becomes smooth. For mismatched shapes, use GSAP MorphSVG or Flubber.js.
Do I need JavaScript to morph blobs?
No — for two same-point-count blobs, the CSS d property in @keyframes morphs them with zero JavaScript. You only need a library (GSAP MorphSVG, Flubber.js) when the two shapes have different command counts or when you morph to a non-blob like a circle.
What is the CSS d property?
It lets you animate the d attribute of an SVG <path> using CSS transitions and keyframes, e.g. d: path('M… Z'). It is supported in current versions of Chrome, Firefox, and Safari. It interpolates linearly between command values, which is why it needs matching command counts to look right.
How do I make a blob 'float' without morphing?
Animate transform on the SVG element — translateY for bob, rotate for drift, scale for a gentle pulse. Because the generator emits an asymmetric shape, a small rotation makes it look organically alive. Transforms run on the compositor, so this is the cheapest animation option.
Why does GSAP MorphSVG morph smoother than CSS?
MorphSVG analyses both paths and subdivides the simpler one to match the control-point count of the more complex one before interpolating. The CSS d property does no such matching — it interpolates command-by-command, so unequal counts break. MorphSVG also lets you control how points map between shapes.
Can I animate the blob's colour?
Yes, but in CSS — the generator only writes a solid fill. Transition or keyframe the fill property on the <path>. For a gradient that animates, add a <linearGradient> in <defs>, point fill at it, and animate the stop-color values. None of that comes from the generator.
How do I respect reduced motion?
Wrap every blob animation in @media (prefers-reduced-motion: reduce) { .blob, .blob path { animation: none; transition: none; } }. Users who enabled reduced motion in their OS see a static blob. Keep the blob visible — removing it can cause layout shift.
Does morphing the path cause layout jank?
No, as long as the SVG element's box size is fixed — and the generator's output has fixed width/height (400×400). Changing d repaints the path but does not reflow the page. Use transform/opacity for any positional motion to stay off the layout path entirely.
Can I morph between three or more blobs?
Yes. With the CSS d property, add intermediate keyframe percentages each with a path of the same command count. With GSAP, chain morphSVG tweens in a timeline. All shapes in the sequence must share a command structure (CSS) or be matched by the library (GSAP/Flubber).
What complexity is too expensive to morph?
CSS d morphing cost scales with the number of commands. Points 6–8 blobs (5–7 C segments) morph at 60fps on virtually all devices. Many Points-10 blobs morphing at once can drop frames on older mobile GPUs. Profile on a mid-range Android device and prefer transform-drift for background decoration.
Should background blobs morph or drift?
For background decoration, prefer transform-based drift — it is compositor-only and far cheaper than morphing. Reserve d-property or GSAP morphing for a single hero accent where the shape change is the point. Mixing many simultaneous morphs is the most common cause of scroll jank.
Where do I get the blob paths to animate?
From the SVG Blob Generator: set a Points value, generate twice, copy both d values. For a curated set of morph pairs across a whole UI, generate them in bulk via the runner — see the batch generation guide.
Privacy first
Every JAD SVG tool runs entirely in your browser using the DOM API and Canvas. Your SVG files never leave your device — verified by zero outbound network requests during processing.