>_htmlhub
library/text & typography/envato-liquid-metal-text

Liquid Metal Text morph

Live previewPerformance varies by device
envato-liquid-metal-text.html

No account needed to copy or download. Check dependencies and thelicense status before publishing.

<!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.

Source Code
Copied to clipboard