How do you create liquid, blob and metaball effects?

Liquid effects make shapes flow, merge and split like a fluid. Metaballs are usually made with an SVG filter, a Gaussian blur followed by a high-contrast colour matrix (the “goo” technique); blobs morph by animating border-radius or SVG paths, and water ripples use canvas or WebGL.

How to choose, performance and accessibility
  • Use Blob Morph or Fluid Gradient as a soft decorative accent, Liquid Button for a playful call to action, and Metaballs or Lava Lamp for an eye-catching hero.
  • SVG filters are costly on large areas, so keep them to small zones, pause animations that are off screen, and show a static shape for prefers-reduced-motion.
  • Metaballs, Blob Morph, AI Shape Morph, AI Color Shift, Generative Glitch and AI Typo Morph are free with their code; the other liquid effects come with Premium.

Metaballs

Organic blobs that merge together with a surface tension effect.

Canvas Animation Organic
View source code
HTML
<div class="demo-preview">
  <div class="metaballs-container">
    <canvas id="metaballs-canvas"></canvas>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.metaballs-container {
  width: 100%;
  height: 100%;
  position: relative;
}

#metaballs-canvas {
  width: 100%;
  height: 100%;
}
JavaScript
(function() {
  // ============================================
  // 1. METABALLS - Canvas Implementation
  // ============================================
  (function() {
    const canvas = document.getElementById('metaballs-canvas');
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const container = canvas.parentElement;

    function resize() {
      canvas.width = container.offsetWidth;
      canvas.height = container.offsetHeight;
    }
    resize();
    window.addEventListener('resize', resize);

    const balls = [];
    const numBalls = 6;

    for (let i = 0; i < numBalls; i++) {
      balls.push({
        x: Math.random() * canvas.width,
        y: Math.random() * canvas.height,
        vx: (Math.random() - 0.5) * 2,
        vy: (Math.random() - 0.5) * 2,
        radius: 30 + Math.random() * 40
      });
    }

    function drawMetaballs() {
      const imageData = ctx.createImageData(canvas.width, canvas.height);
      const data = imageData.data;

      for (let x = 0; x < canvas.width; x++) {
        for (let y = 0; y < canvas.height; y++) {
          let sum = 0;

          for (const ball of balls) {
            const dx = x - ball.x;
            const dy = y - ball.y;
            const dist = Math.sqrt(dx * dx + dy * dy);
            sum += (ball.radius * ball.radius) / (dist * dist + 1);
          }

          const idx = (y * canvas.width + x) * 4;

          if (sum > 1) {
            const intensity = Math.min(sum - 1, 1);
            data[idx] = 99 + intensity * 50; // R
            data[idx + 1] = 102 + intensity * 50; // G
            data[idx + 2] = 241; // B
            data[idx + 3] = 255; // A
          } else {
            data[idx] = 26;
            data[idx + 1] = 26;
            data[idx + 2] = 36;
            data[idx + 3] = 255;
          }
        }
      }

      ctx.putImageData(imageData, 0, 0);
    }

    function updateBalls() {
      for (const ball of balls) {
        ball.x += ball.vx;
        ball.y += ball.vy;

        if (ball.x < ball.radius || ball.x > canvas.width - ball.radius) {
          ball.vx *= -1;
        }
        if (ball.y < ball.radius || ball.y > canvas.height - ball.radius) {
          ball.vy *= -1;
        }
      }
    }

    function animate() {
      updateBalls();
      drawMetaballs();
      requestAnimationFrame(animate);
    }

    animate();
  })();
})();

Water Ripple

Realistic ripple effect simulated with wave propagation.

Canvas Interactive Physics

Liquid Button

Button with animated liquid fill effect on hover.

CSS Hover Button

Dripping Text

Text with a dripping effect that falls continuously.

CSS SVG Filter Text

Bubble Rise

Translucent bubbles rising with organic movements.

CSS Animation Particles

Lava Lamp

Floating lava lamp-style blobs with organic deformations.

CSS Animation Blur

Mercury Drops

Metallic drops with realistic reflections and elastic bounces.

CSS 3D Metallic

Wave Surface

Animated water surface with multiple wave layers.

CSS SVG Layers

Splash Effect

Interactive splash effect with particles and droplets.

Canvas Interactive Particles

Fluid Gradient

Animated gradient that flows like liquid with organic motion.

CSS Gradient Blur

WebGL Fluid Simulation

Neon ink flows under the cursor, swirls and fades; a click bursts a fresh colour. With no interaction, the motion carries on by itself.

💡 Perfect for: landing-page heroes, agency homepages, playful 404 pages.

WebGL Shader Fluid Interactive Bloom Premium
BLOB

Blob Morph

Organic shape that continuously morphs between different fluid silhouettes via border-radius animation.

CSS Organic Keyframes
View source code
HTML
<div class="demo-preview">
  <div class="blob-morph">BLOB</div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.blob-morph {
  width: 180px;
  height: 180px;
  background: linear-gradient(135deg, #a855f7, #ec4899);
  animation: blobMorph 8s ease-in-out infinite;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 1rem;
  color: white;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  box-shadow:
    0 0 40px rgba(168, 85, 247, 0.4),
    0 0 80px rgba(236, 72, 153, 0.2);
  transition: transform 0.3s ease;
}

.blob-morph:hover {
  transform: scale(1.08);
}

@keyframes blobMorph {
  0% {
    border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
  }

  14% {
    border-radius: 40% 60% 70% 30% / 50% 60% 40% 50%;
  }

  28% {
    border-radius: 70% 30% 50% 50% / 30% 50% 60% 70%;
  }

  42% {
    border-radius: 30% 60% 70% 40% / 50% 30% 70% 60%;
  }

  56% {
    border-radius: 50% 50% 30% 70% / 70% 40% 60% 30%;
  }

  70% {
    border-radius: 40% 70% 60% 30% / 40% 60% 30% 70%;
  }

  84% {
    border-radius: 70% 40% 40% 60% / 60% 50% 50% 40%;
  }

  100% {
    border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
  }
}
JavaScript
/* Pure CSS — no JavaScript required */

Icon Morph

Hamburger icon that transforms into a close cross with smooth CSS transitions on click.

CSS JS Interaction

Shape Shifter

Shape that cycles between circle, square, triangle, hexagon and star using clip-path transitions.

CSS clip-path Cycle

Button Morph

Button that morphs into a loading spinner, then into a validation checkmark on click.

CSS JS UX

Text Morph

Text that morphs between multiple words with blur and opacity for a smooth transition.

CSS JS Typography

Card Morph

Compact card that expands and transforms into a detailed panel on click with smooth transitions.

CSS JS Layout

SVG Path Morph

SVG shape that morphs between star, heart and circle by animating the path attribute.

SVG JS Path

Liquid Morph

Liquid drops that merge and separate using the CSS filter blur + contrast trick for an organic effect.

CSS SVG Filter Organic

Avatar Morph

Circular avatar that transforms into a rectangular card with user information on hover.

CSS Hover Profile

Toggle Morph

Toggle switch whose knob changes shape while sliding: the circle deforms into a pill before returning to its initial shape.

CSS JS UI

AI & Intelligence

AI Shape Morph

SVG shapes that smoothly interpolate between different silhouettes with organic transitions.

Canvas Morphing Animation
View source code
HTML
<div class="demo-preview">
  <div class="ai-shape-morph-container">
    <canvas id="ai-shape-canvas"></canvas>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.ai-shape-morph-container {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ai-shape-morph-container canvas {
  width: 100%;
  height: 100%;
}
JavaScript
(function() {
  // ============================================
  // AI & Intelligence Effects
  // ============================================

  // 1. AI Shape Morph
  (function() {
    const canvas = document.getElementById('ai-shape-canvas');
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const container = canvas.parentElement;

    function resize() {
      canvas.width = container.offsetWidth;
      canvas.height = container.offsetHeight;
    }
    resize();

    const shapes = [
      // Circle points
      Array.from({
        length: 12
      }, (_, i) => {
        const a = (i / 12) * Math.PI * 2;
        return {
          x: Math.cos(a) * 0.35,
          y: Math.sin(a) * 0.35
        };
      }),
      // Star points
      Array.from({
        length: 12
      }, (_, i) => {
        const a = (i / 12) * Math.PI * 2;
        const r = i % 2 === 0 ? 0.4 : 0.2;
        return {
          x: Math.cos(a) * r,
          y: Math.sin(a) * r
        };
      }),
      // Square points
      Array.from({
        length: 12
      }, (_, i) => {
        const t = i / 12;
        const side = Math.floor(t * 4);
        const p = (t * 4) % 1;
        const coords = [{
            x: -0.3 + p * 0.6,
            y: -0.3
          },
          {
            x: 0.3,
            y: -0.3 + p * 0.6
          },
          {
            x: 0.3 - p * 0.6,
            y: 0.3
          },
          {
            x: -0.3,
            y: 0.3 - p * 0.6
          }
        ];
        return coords[side];
      })
    ];

    let currentShape = 0;
    let progress = 0;
    let morphPoints = shapes[0].map(p => ({
      ...p
    }));

    function animate() {
      progress += 0.008;
      if (progress >= 1) {
        progress = 0;
        currentShape = (currentShape + 1) % shapes.length;
      }

      const nextShape = (currentShape + 1) % shapes.length;
      const eased = 0.5 - 0.5 * Math.cos(progress * Math.PI);

      for (let i = 0; i < morphPoints.length; i++) {
        morphPoints[i].x = shapes[currentShape][i].x + (shapes[nextShape][i].x - shapes[currentShape][i].x) * eased;
        morphPoints[i].y = shapes[currentShape][i].y + (shapes[nextShape][i].y - shapes[currentShape][i].y) * eased;
      }

      ctx.clearRect(0, 0, canvas.width, canvas.height);
      const cx = canvas.width / 2;
      const cy = canvas.height / 2;
      const scale = Math.min(canvas.width, canvas.height);

      const gradient = ctx.createLinearGradient(cx - 80, cy - 80, cx + 80, cy + 80);
      gradient.addColorStop(0, '#6366f1');
      gradient.addColorStop(0.5, '#a855f7');
      gradient.addColorStop(1, '#ec4899');

      ctx.beginPath();
      ctx.moveTo(cx + morphPoints[0].x * scale, cy + morphPoints[0].y * scale);
      for (let i = 1; i < morphPoints.length; i++) {
        const prev = morphPoints[i - 1];
        const curr = morphPoints[i];
        const cpx = cx + (prev.x + curr.x) / 2 * scale;
        const cpy = cy + (prev.y + curr.y) / 2 * scale;
        ctx.quadraticCurveTo(cx + prev.x * scale, cy + prev.y * scale, cpx, cpy);
      }
      ctx.closePath();
      ctx.fillStyle = gradient;
      ctx.fill();

      requestAnimationFrame(animate);
    }
    animate();
    window.addEventListener('resize', resize);
  })();
})();

Generative Flow Field

Perlin noise-generated flow field with particles following force lines.

Canvas Perlin Particles

Neural Net Viz

Animated neuron graph with pulsating connections and dynamic activations.

Canvas Network AI

AI Color Shift

Dynamically generated color palette in OKLCH with fluid transitions between harmonies.

CSS OKLCH Colors
View source code
HTML
<div class="demo-preview">
  <div class="ai-color-shift" id="aiColorShift">
    <div class="ai-color-swatch"></div>
    <div class="ai-color-swatch"></div>
    <div class="ai-color-swatch"></div>
    <div class="ai-color-swatch"></div>
    <div class="ai-color-swatch"></div>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.ai-color-shift {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  padding: 20px;
}

.ai-color-swatch {
  border-radius: 12px;
  transition: background 1.5s ease;
}
JavaScript
(function() {
  // 4. AI Color Shift
  (function() {
    const container = document.getElementById('aiColorShift');
    if (!container) return;
    const swatches = container.querySelectorAll('.ai-color-swatch');
    let hueBase = 0;

    function updateColors() {
      hueBase = (hueBase + 0.3) % 360;
      swatches.forEach((swatch, i) => {
        const hue = (hueBase + i * 72) % 360;
        const lightness = 50 + Math.sin(hueBase * 0.02 + i) * 15;
        swatch.style.background = `oklch(${lightness}% 0.2 ${hue})`;
      });
      requestAnimationFrame(updateColors);
    }
    updateColors();
  })();
})();

Swarm Intelligence

Swarm particles with emergent behavior: cohesion, separation and alignment.

Canvas Boids Emergent
GLITCH

Generative Glitch

Generative glitch art with random slicing and animated chromatic effects.

CSS Glitch Art
View source code
HTML
<div class="demo-preview">
  <div class="ai-glitch-container">
    <span class="ai-glitch-text" data-text="GLITCH">GLITCH</span>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.ai-glitch-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #111;
}

.ai-glitch-text {
  font-size: 2.5rem;
  font-weight: 800;
  color: #fff;
  position: relative;
}

.ai-glitch-text::before,
.ai-glitch-text::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.ai-glitch-text::before {
  animation: aiGlitch1 2s infinite linear alternate-reverse;
  clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
  color: #0ff;
}

.ai-glitch-text::after {
  animation: aiGlitch2 3s infinite linear alternate-reverse;
  clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%);
  color: #f0f;
}

@keyframes aiGlitch1 {
  0% {
    transform: translate(0);
  }

  20% {
    transform: translate(-3px, 2px);
  }

  40% {
    transform: translate(3px, -1px);
  }

  60% {
    transform: translate(-2px, -2px);
  }

  80% {
    transform: translate(2px, 1px);
  }

  100% {
    transform: translate(0);
  }
}

@keyframes aiGlitch2 {
  0% {
    transform: translate(0);
  }

  25% {
    transform: translate(2px, -2px);
  }

  50% {
    transform: translate(-3px, 1px);
  }

  75% {
    transform: translate(1px, 2px);
  }

  100% {
    transform: translate(0);
  }
}
JavaScript
/* Pure CSS — no JavaScript required */

Predictive Grid Morph

Interactive grid that deforms on hover with mouse trajectory prediction.

CSS JS Grid

Deep Dream Pattern

Animated fractal patterns inspired by deep dream with self-similar motifs in motion.

Canvas Fractal Generative

AI Typo Morph

Letters that fluidly transform between different words with a typographic morphing effect.

JS Typo Morph
View source code
HTML
<div class="demo-preview">
  <div class="ai-typo-morph">
    <div class="ai-typo-word" id="aiTypoWord"></div>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.ai-typo-morph {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ai-typo-word {
  font-size: 2.5rem;
  font-weight: 800;
  background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: 2px;
}
JavaScript
(function() {
  // 9. AI Typo Morph
  (function() {
    const wordEl = document.getElementById('aiTypoWord');
    if (!wordEl) return;

    const words = ['DESIGN', 'CREATE', 'MORPH', 'DREAM', 'BUILD'];
    let currentWord = 0;
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%';

    function morphTo(target) {
      const current = wordEl.textContent || '';
      const maxLen = Math.max(current.length, target.length);
      let iterations = 0;
      const interval = setInterval(() => {
        let result = '';
        for (let i = 0; i < maxLen; i++) {
          if (i < target.length) {
            if (iterations > i * 2) {
              result += target[i];
            } else {
              result += chars[Math.floor(Math.random() * chars.length)];
            }
          }
        }
        wordEl.textContent = result;
        iterations++;
        if (iterations > maxLen * 2 + 5) {
          clearInterval(interval);
          wordEl.textContent = target;
        }
      }, 50);
    }

    wordEl.textContent = words[0];

    var typoInterval = setInterval(() => {
      currentWord = (currentWord + 1) % words.length;
      morphTo(words[currentWord]);
    }, 3000);
  })();
})();

Mesh Distortion AI

Deformable mesh gradient with mouse interactions and reactive organic deformations.

Canvas Mesh Interactive

Frequently Asked Questions

How to create metaballs in CSS? +

CSS metaballs use an SVG filter with feGaussianBlur and feColorMatrix. Place colored circles, apply blur, then the color matrix with a high threshold to merge shapes where they overlap.

How to animate a blob in CSS? +

Use border-radius with 8 values (e.g.: 30% 70% 70% 30% / 30% 30% 70% 70%) and animate them with @keyframes. Each frame changes the values to create organic movement. Add a slow rotation for more dynamism.

What is the difference between liquid and glassmorphism? +

Glassmorphism creates a frosted glass effect (static, translucent). Liquid creates organic shapes that move and deform (dynamic, motion). Both can be combined for spectacular effects.

Are liquid animations performant? +

CSS animations (border-radius, transform) are GPU-optimized. SVG filter effects (metaballs) are heavier -- limit to 2-3 blobs. For complex effects, use canvas with requestAnimationFrame.

Can liquid effects be used on mobile? +

Yes, by simplifying: reduce the number of blobs, use CSS animations rather than canvas, and lower the complexity of SVG filters. Test on a real device as performance varies.

Similar Categories