You've probably seen the gooey effect on creative portfolios and interactive menus: circles that squish and stick together when they overlap, blobs that merge and separate as they animate. It looks like it requires a physics engine or canvas-based rendering, but it's actually a clever combination of an SVG filter and a CSS blur + contrast trick that runs entirely in the browser's compositing pipeline. The CSS/SVG Gooey Effect Demo lets you tune every parameter and copy the ready-to-use code.

How the gooey effect works

The trick uses two CSS filters applied together on the parent container:

  1. Gaussian blur — blurs all the child elements, making them bleed into each other where they're close
  2. High contrast — cranks the contrast to an extreme level, which causes the soft blurred edges to snap back to hard edges — but only where the combined opacity is above a threshold

The result: where two blurred circles overlap or nearly touch, their blurred edges blend into a single connected shape. The contrast filter then renders that merged region as a solid filled shape, making them look like they've merged into one blob.

In CSS this looks like:

.gooey-container {
  filter: url('#gooey-filter') blur(0px);
}

/* In SVG (hidden, placed anywhere in the DOM): */
<svg xmlns="http://www.w3.org/2000/svg" style="position:absolute;width:0;height:0">
  <defs>
    <filter id="gooey-filter">
      <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
      <feColorMatrix in="blur" mode="matrix"
        values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 20 -10"
        result="gooey" />
      <feComposite in="SourceGraphic" in2="gooey" operator="atop" />
    </filter>
  </defs>
</svg>

Breaking down the SVG filter primitives

feGaussianBlur

The stdDeviation controls how much the shapes bleed into each other. Higher values create a longer "neck" between merging blobs — they attract each other from further away. Lower values require shapes to be closer before they connect. The demo tool lets you adjust this in real time to find the right value for your use case.

feColorMatrix

This is the contrast step. The matrix values 0 0 0 20 -10 on the alpha row mean: multiply the alpha channel by 20, then subtract 10 (which in alpha space means subtract 2.55 × 10 ≈ 2550/255 of alpha). Any pixel with alpha below about 0.5 gets pushed to 0 (transparent); any pixel with alpha above 0.5 gets pushed to 1 (fully opaque). This is what creates the hard snap-to-edge behaviour.

Tweaking these values changes the threshold at which shapes merge — the demo exposes this as a simple "stickiness" slider.

feComposite

The optional composite step at the end restores the original colours of the source elements. Without it, the merged shape inherits the colour of the underlying element's alpha-composited result (usually fine), but adding feComposite in="SourceGraphic" in2="gooey" operator="atop" clips the original source graphic to only show within the gooey shape — giving you full colour fidelity.

What you can build with it

Browser support and performance

SVG filters are well-supported across all modern browsers — Chrome, Firefox, Safari, and Edge all render the gooey effect correctly. Performance is generally good for a moderate number of animated elements (up to ~20 simultaneous blobs animating), but the Gaussian blur + contrast combination is GPU-intensive. Animating hundreds of elements simultaneously will cause frame drops on lower-end devices.

A practical tip: apply will-change: transform to animated child elements and transform: translateZ(0) to the container to encourage GPU compositing, which typically halves the paint cost.

Build your gooey effect →
Adjust blob count, size, blur intensity, and stickiness — then copy the ready-to-use HTML and CSS.

Open the demo →