<!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>
<!-- 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>
@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;
}
// 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)`;
});
});