live - 60fps 1920 x 1080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Liquid Metal Text</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Syncopate:wght@700&display=swap');
body {
margin: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #000;
overflow: hidden;
font-family: 'Syncopate', sans-serif;
}
/*
* The core magic: applying an SVG filter to a div containing text.
* We blur the text heavily, then use a color matrix to sharpen the blur
* perfectly, creating a liquid, gooey connection between letters.
*/
#liquid-container {
filter: url(#liquid-filter);
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.text-layer {
position: absolute;
font-size: 8vw;
font-weight: 900;
text-transform: uppercase;
letter-spacing: -2vw;
/* Crucial: letters must overlap slightly for the blob effect */
color: #fff;
white-space: nowrap;
display: flex;
}
.letter {
display: inline-block;
transition: transform 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
/* The Chrome styling added AFTER the filter is applied using a pseudo-element wrapper or background clip */
.chrome-text {
background: linear-gradient(180deg,
#fff 0%,
#888 30%,
#111 50%,
#555 52%,
#fff 100%);
background-clip: text;
-webkit-background-clip: text;
/* To make the gradient visible, the base text is transparent,
but the gooey filter requires solid color.
Workaround: Apply gooey filter to a solid white layer behind,
then overlay the chrome layer perfectly on top. */
}
/* Overlay text that is sharp and metallic */
#front-text {
filter: drop-shadow(0px 10px 20px rgba(0, 0, 0, 0.8));
letter-spacing: 0vw;
/* Base spacing */
}
#back-goo {
/* This is the layer that gets filtered */
letter-spacing: 0vw;
}
/* Interactive Hover State */
.container-wrapper {
position: relative;
cursor: pointer;
}
.container-wrapper:hover .letter {
transform: translateY(-20px) scaleY(1.5);
color: #00ffff;
/* The goo changes color */
}
.container-wrapper:hover #front-text .letter {
background: linear-gradient(180deg,
#0ff 0%,
#0055ff 30%,
#001133 50%,
#0033aa 52%,
#0ff 100%);
background-clip: text;
-webkit-background-clip: text;
}
/* Stagger letter animations */
.letter:nth-child(1) {
transition-delay: 0.0s;
}
.letter:nth-child(2) {
transition-delay: 0.05s;
}
.letter:nth-child(3) {
transition-delay: 0.1s;
}
.letter:nth-child(4) {
transition-delay: 0.15s;
}
.letter:nth-child(5) {
transition-delay: 0.2s;
}
.letter:nth-child(6) {
transition-delay: 0.25s;
}
</style>
</head>
<body>
<!-- The SVG Filter Definition -->
<svg width="0" height="0" style="position: absolute;">
<defs>
<filter id="liquid-filter">
<!-- 1. Blur the source image heavily -->
<feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur" />
<!-- 2. Sharpen the alpha channel back up. The matrix multiplies alpha by 18 and subtracts 7. -->
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 40 -15"
result="goo" />
<!-- 3. Blend original graphic over the goo for crispness (optional, but good for text) -->
<feComposite in="SourceGraphic" in2="goo" operator="atop" />
</filter>
</defs>
</svg>
<div class="container-wrapper">
<!-- The background layer that gets gooey -->
<div id="liquid-container">
<div class="text-layer" id="back-goo">
<span class="letter">L</span>
<span class="letter">I</span>
<span class="letter">Q</span>
<span class="letter">U</span>
<span class="letter">I</span>
<span class="letter">D</span>
</div>
</div>
<!-- The foreground layer that receives the metallic gradient -->
<div class="text-layer chrome-text" id="front-text">
<span class="letter">L</span>
<span class="letter">I</span>
<span class="letter">Q</span>
<span class="letter">U</span>
<span class="letter">I</span>
<span class="letter">D</span>
</div>
</div>
<script>
// Optional: Make characters repel from mouse horizontally to exaggerate the "liquid" separation
const wrapper = document.querySelector('.container-wrapper');
const frontLetters = document.querySelectorAll('#front-text .letter');
const backLetters = document.querySelectorAll('#back-goo .letter');
wrapper.addEventListener('mousemove', (e) => {
const rect = wrapper.getBoundingClientRect();
const relX = e.clientX - rect.left;
frontLetters.forEach((letter, index) => {
const letterRect = letter.getBoundingClientRect();
const letterCenter = letterRect.left - rect.left + (letterRect.width / 2);
const distance = relX - letterCenter;
// Repel letters away from mouse
let shift = 0;
if (Math.abs(distance) < 150) { // Hover radius
shift = distance > 0 ? -15 : 15;
}
const transform = `translateX(${shift}px)`;
letter.style.transform = transform;
backLetters[index].style.transform = transform;
});
});
wrapper.addEventListener('mouseleave', () => {
frontLetters.forEach((letter, index) => {
letter.style.transform = `translateX(0px)`;
backLetters[index].style.transform = `translateX(0px)`;
});
});
</script>
</body>
</html> About this animation
An intense visual text effect utilizing complex SVG feColorMatrix and feGaussianBlur filters to simulate liquid chrome.
Under the hood
SVG ColorMatrix Blending
This leverages a highly complex SVG filter applied natively to text nodes. First,
feGaussianBlur heavily blurs the letters together. Second, an feColorMatrix aggressively crushes the alpha channel to sharpen the blurred edges back out. The result is letters that organically blob and tear away from each other mathematically. Related