Comment créer des effets liquides, des blobs et des metaballs ?

Les effets liquides font couler, fusionner et se séparer des formes comme un fluide. Les metaballs s'obtiennent en général avec un filtre SVG, un flou gaussien suivi d'une matrice de couleurs très contrastée (la technique « goo ») ; les blobs se déforment en animant border-radius ou des tracés SVG, et les ondulations d'eau utilisent canvas ou WebGL.

Comment choisir, performances et accessibilité
  • Utilisez Blob Morph ou Fluid Gradient comme accent décoratif discret, Liquid Button pour un appel à l'action ludique, et Metaballs ou Lava Lamp pour un héros qui attire l'œil.
  • Les filtres SVG coûtent cher sur de grandes surfaces : limitez-les à de petites zones, mettez en pause les animations hors de l'écran et affichez une forme fixe pour prefers-reduced-motion.
  • Metaballs, Blob Morph, AI Shape Morph, AI Color Shift, Generative Glitch et AI Typo Morph sont gratuits avec leur code ; les autres effets liquides sont inclus dans Premium.

Metaballs

Blobs organiques qui fusionnent ensemble avec un effet de tension de surface.

Canvas Animation Organic
Voir le code source
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

Effet d'ondulation réaliste simule avec propagation des vagues.

Canvas Interactive Physics

Liquid Button

Bouton avec effet de remplissage liquide animé au survol.

CSS Hover Button

Dripping Text

Texte avec effet de gouttes qui tombent continuellement.

CSS SVG Filter Text

Bubble Rise

Bulles translucides qui montent avec des mouvements organiques.

CSS Animation Particles

Lava Lamp

Blobs flottants style lampe a lave avec déformations organiques.

CSS Animation Blur

Mercury Drops

Gouttes métalliques avec reflets réalistes et rebonds élastiques.

CSS 3D Metallic

Wave Surface

Surface d'eau animée avec plusieurs couches de vagues.

CSS SVG Layers

Splash Effect

Effet d'éclaboussure interactif avec particules et gouttelettes.

Canvas Interactive Particles

Fluid Gradient

Gradient animé qui coule comme un liquide avec mouvement organique.

CSS Gradient Blur

WebGL Fluid Simulation

De l'encre néon coule sous le curseur, tourbillonne et s'estompe ; un clic fait éclater une nouvelle couleur. Sans interaction, le mouvement continue tout seul.

💡 Idéal pour : hero de landing page, accueil d'agence, page 404 ludique.

WebGL Shader Fluide Interactif Bloom Premium
BLOB

Blob Morph

Forme organique qui se métamorphose continuellement entre différentes silhouettes fluides via l'animation du border-radius.

CSS Organique Keyframes
Voir le code source
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
/* CSS pur — aucun JavaScript requis */

Icon Morph

Icône hamburger qui se transforme en croix de fermeture avec des transitions CSS fluides au clic.

CSS JS Interaction

Shape Shifter

Forme qui cycle entre cercle, carre, triangle, hexagone et étoile grâce aux transitions clip-path.

CSS clip-path Cycle

Button Morph

Bouton qui se métamorphose en spinner de chargement, puis en coche de validation au clic.

CSS JS UX

Text Morph

Texte qui se métamorphose entre plusieurs mots avec un effet de flou et opacité pour une transition douce.

CSS JS Typographie

Card Morph

Carte compacte qui s'agrandit et se transforme en panneau détaillé au clic avec des transitions fluides.

CSS JS Layout

SVG Path Morph

Forme SVG qui se métamorphose entre étoile, coeur et cercle en animant l'attribut de chemin.

SVG JS Path

Liquid Morph

Gouttes liquides qui fusionnent et se séparent grâce à l'astuce CSS filter blur + contrast pour un effet organique.

CSS SVG Filter Organique

Avatar Morph

Avatar circulaire qui se transforme en carte rectangulaire avec informations utilisateur au survol.

CSS Hover Profil

Toggle Morph

Interrupteur dont le curseur change de forme en glissant : le cercle se déforme en pilule avant de reprendre sa forme initiale.

CSS JS UI

AI & Intelligence

AI Shape Morph

Formes SVG qui s'interpolent fluidement entre différentes silhouettes avec des transitions organiques.

Canvas Morphing Animation
Voir le code source
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

Champ de flux génère par bruit Perlin avec des particules qui suivent les lignes de force.

Canvas Perlin Particules

Neural Net Viz

Graphe animé de neurones avec des connexions pulsantes et des activations dynamiques.

Canvas Réseau AI

AI Color Shift

Palette de couleurs générée dynamiquement en OKLCH avec transitions fluides entre harmonies.

CSS OKLCH Couleurs
Voir le code source
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

Particules en essaim avec comportement émergent : cohésion, séparation et alignement.

Canvas Boids Émergent
GLITCH

Generative Glitch

Art glitch génératif avec découpage aléatoire et effets chromatiques animés.

CSS Glitch Art
Voir le code source
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
/* CSS pur — aucun JavaScript requis */

Predictive Grid Morph

Grille interactive qui se déforme au survol avec une prédiction de trajectoire de la souris.

CSS JS Grid

Deep Dream Pattern

Patterns fractals animés inspirés du deep dream avec des motifs auto-similaires en mouvement.

Canvas Fractal Génératif

AI Typo Morph

Lettres qui se transforment fluidement entre différents mots avec un effet de morphing typographique.

JS Typo Morph
Voir le code source
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

Mesh gradient deformable avec interactions de souris et déformations organiques réactives.

Canvas Mesh Interactif

Questions fréquentes

Comment créer des metaballs en CSS ? +

Les metaballs CSS utilisent un filtre SVG avec feGaussianBlur et feColorMatrix. Placez des cercles colorés, appliquez le blur, puis le color matrix avec un seuil élevé pour fusionner les formes là où elles se chevauchent.

Comment animer un blob en CSS ? +

Utilisez border-radius avec 8 valeurs (ex: 30% 70% 70% 30% / 30% 30% 70% 70%) et animez-les avec @keyframes. Chaque frame change les valeurs pour créer un mouvement organique. Ajoutez un rotation lente pour plus de dynamisme.

Quelle est la différence entre liquid et glassmorphism ? +

Le glassmorphism crée un effet de verre dépoli (statique, translucide). Le liquid crée des formes organiques qui bougent et se déforment (dynamique, mouvement). Les deux peuvent être combines pour des effets spectaculaires.

Les animations liquid sont-elles performantes ? +

Les animations CSS (border-radius, transform) sont optimisées GPU. Les effets SVG filter (metaballs) sont plus lourds — limitez à 2-3 blobs. Pour des effets complexes, utilisez canvas avec requestAnimationFrame.

Peut-on utiliser des effets liquid sur mobile ? +

Oui, en simplifiant : réduisez le nombre de blobs, utilisez des animations CSS plutôt que canvas, et baissez la complexité des filtres SVG. Testez sur un appareil réel car les performances varient.

Catégories similaires