Liquid, Morphing & Animations Organiques
Effets liquides, metaballs, morphing et shape-shifting.
Mis à jour le
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.
Voir le code source
<div class="demo-preview">
<div class="metaballs-container">
<canvas id="metaballs-canvas"></canvas>
</div>
</div>.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%;
}(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.
Liquid Button
Bouton avec effet de remplissage liquide animé au survol.
Dripping Text
Texte avec effet de gouttes qui tombent continuellement.
Bubble Rise
Bulles translucides qui montent avec des mouvements organiques.
Lava Lamp
Blobs flottants style lampe a lave avec déformations organiques.
Mercury Drops
Gouttes métalliques avec reflets réalistes et rebonds élastiques.
Wave Surface
Surface d'eau animée avec plusieurs couches de vagues.
Splash Effect
Effet d'éclaboussure interactif avec particules et gouttelettes.
Fluid Gradient
Gradient animé qui coule comme un liquide avec mouvement organique.
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.
Blob Morph
Forme organique qui se métamorphose continuellement entre différentes silhouettes fluides via l'animation du border-radius.
Voir le code source
<div class="demo-preview">
<div class="blob-morph">BLOB</div>
</div>.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%;
}
}/* CSS pur — aucun JavaScript requis */Icon Morph
Icône hamburger qui se transforme en croix de fermeture avec des transitions CSS fluides au clic.
Shape Shifter
Forme qui cycle entre cercle, carre, triangle, hexagone et étoile grâce aux transitions clip-path.
Button Morph
Bouton qui se métamorphose en spinner de chargement, puis en coche de validation au clic.
Text Morph
Texte qui se métamorphose entre plusieurs mots avec un effet de flou et opacité pour une transition douce.
Card Morph
Carte compacte qui s'agrandit et se transforme en panneau détaillé au clic avec des transitions fluides.
SVG Path Morph
Forme SVG qui se métamorphose entre étoile, coeur et cercle en animant l'attribut de chemin.
Liquid Morph
Gouttes liquides qui fusionnent et se séparent grâce à l'astuce CSS filter blur + contrast pour un effet organique.
Avatar Morph
Avatar circulaire qui se transforme en carte rectangulaire avec informations utilisateur au survol.
Toggle Morph
Interrupteur dont le curseur change de forme en glissant : le cercle se déforme en pilule avant de reprendre sa forme initiale.
AI & Intelligence
AI Shape Morph
Formes SVG qui s'interpolent fluidement entre différentes silhouettes avec des transitions organiques.
Voir le code source
<div class="demo-preview">
<div class="ai-shape-morph-container">
<canvas id="ai-shape-canvas"></canvas>
</div>
</div>.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%;
}(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.
Neural Net Viz
Graphe animé de neurones avec des connexions pulsantes et des activations dynamiques.
AI Color Shift
Palette de couleurs générée dynamiquement en OKLCH avec transitions fluides entre harmonies.
Voir le code source
<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>.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;
}(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.
Generative Glitch
Art glitch génératif avec découpage aléatoire et effets chromatiques animés.
Voir le code source
<div class="demo-preview">
<div class="ai-glitch-container">
<span class="ai-glitch-text" data-text="GLITCH">GLITCH</span>
</div>
</div>.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);
}
}/* 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.
Deep Dream Pattern
Patterns fractals animés inspirés du deep dream avec des motifs auto-similaires en mouvement.
AI Typo Morph
Lettres qui se transforment fluidement entre différents mots avec un effet de morphing typographique.
Voir le code source
<div class="demo-preview">
<div class="ai-typo-morph">
<div class="ai-typo-word" id="aiTypoWord"></div>
</div>
</div>.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;
}(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.