Gooey Text Morph — Free HTML CSS JS Goo Filter Snippet
Gooey Text Morph · Animations · Plain HTML, CSS & JS · Live preview
Copy & paste
Source Code
<div class="gt-stage">
<svg width="0" height="0"><filter id="gtGoo"><feGaussianBlur in="SourceGraphic" stdDeviation="7" result="b"/><feColorMatrix in="b" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -8"/></filter></svg>
<div class="gt-morph" id="gtMorph">
<span class="gt-word gt-a" id="gtA">CREATE</span>
<span class="gt-word gt-b" id="gtB">SHIP</span>
</div>
<p class="gt-sub">Two words melt and reform on a goo filter</p>
</div>*{box-sizing:border-box;margin:0;padding:0}
body{font-family:system-ui,-apple-system,sans-serif;background:#06060e;color:#fff;display:flex;justify-content:center;align-items:center;min-height:100vh;flex-direction:column;gap:18px}
.gt-stage{text-align:center}
.gt-morph{position:relative;height:120px;width:min(90vw,520px);filter:url(#gtGoo)}
.gt-word{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:clamp(44px,11vw,96px);font-weight:900;letter-spacing:-.03em;color:#818cf8}
.gt-a{animation:gtA 4s infinite}
.gt-b{animation:gtB 4s infinite}
@keyframes gtA{0%,38%{opacity:1;transform:scale(1)}50%,88%{opacity:0;transform:scale(.6)}100%{opacity:1;transform:scale(1)}}
@keyframes gtB{0%,38%{opacity:0;transform:scale(.6)}50%,88%{opacity:1;transform:scale(1)}100%{opacity:0;transform:scale(.6)}}
.gt-sub{color:#6a6a86;font-size:13.5px;letter-spacing:.04em}// The morph itself is pure CSS + the SVG goo filter. JS only rotates a longer
// word list through the two layers, swapping their text once per 4s loop (while
// they are mid-transition) so you always see two words melting together.
var a = document.getElementById('gtA');
var b = document.getElementById('gtB');
var WORDS = ['CREATE', 'SHIP', 'SCALE', 'REPEAT'];
var step = 0;
setInterval(function () {
step++;
a.textContent = WORDS[(step * 2) % WORDS.length];
b.textContent = WORDS[(step * 2 + 1) % WORDS.length];
}, 4000);Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Gooey Text Morph — Words Melting Through an SVG Goo Filter

Gooey text morph is the liquid typography effect where one word appears to melt and reform into the next, the letters blobbing together as they cross-fade — the same metaball look used for gooey menus, applied to type. This snippet builds it with plain HTML, an SVG filter, CSS animation, and a little vanilla JavaScript to cycle through your own list of words.
The SVG goo filter
The morph relies on the classic goo filter, #gtGoo. It blurs the source with feGaussianBlur, then passes the result through a feColorMatrix that sharply boosts the alpha channel (0 0 0 19 -8), thresholding the soft blur back into hard shapes. Applied to a container, this makes any blurred forms inside merge: where two semi-transparent, blurred letters overlap, they fuse into one continuous blob. As one word fades out and another fades in over the same area, their blurred glyphs momentarily melt together — the gooey transition.
Two stacked word layers
Inside the filtered container sit two absolutely-positioned word layers, A and B, occupying the same space. CSS keyframes (gtA and gtB) cross-fade them on a 4-second loop: while A holds at full opacity and scale, B is hidden and shrunk, then they swap, each scaling between 0.6 and 1 as it fades. Because both layers are blurred and overlapping during the handoff, the goo filter fuses their letters mid-transition so the change reads as a liquid morph rather than a simple dissolve. The scale change adds a gravitational "pull" to the melt.
Cycling arbitrary words
The two layers only ever show two words at a time, but JavaScript rotates through a longer WORDS list so the morph keeps presenting new pairs. On each cycle it advances and assigns the next words to the layers while they're transitioning, so words are swapped during their hidden phase — you only ever see two words melting into each other, never a word changing in plain view. Supply any list (a tagline, a set of verbs, feature names) and the loop handles the rest.
Why this approach is cheap
The entire morph is GPU-friendly: the goo filter is applied once to a small container, and only opacity and transform animate — no per-frame JavaScript drawing, no canvas. That keeps it smooth even on modest devices, and the filter is reusable across multiple morphs on a page.
Type and layout
The words are heavy, tightly-tracked, and large (clamp scales them responsively), which gives the blur enough mass to blob convincingly — thin text doesn't goo well because there isn't enough ink to merge. The container has a fixed height so the absolute layers have a stable box to morph within.
Customizing it
Edit the WORDS array, tune the filter's stdDeviation and alpha matrix for more or less gooeyness, change the loop timing, recolor the text, or adjust the scale range in the keyframes for a stronger melt. Pair it with a text generate reveal or a liquid button to extend the gooey theme across a page.
Step by step
How to Use
- 1Paste HTML, CSS, and JSA large word morphs into another on a loop.
- 2Watch the meltLetters blob together as one word becomes the next.
- 3See it cycleNew word pairs keep coming from the word list.
- 4Edit the wordsChange the WORDS array to your own list.
- 5Tune the gooAdjust the filter blur and alpha matrix.
- 6Retime the loopChange the keyframe and interval durations.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
The container has an SVG goo filter: a Gaussian blur followed by a feColorMatrix that boosts the alpha channel to threshold the blur back into hard shapes. Inside, two blurred word layers cross-fade over the same space. During the handoff their blurred letters overlap and the filter fuses them into continuous blobs, so the change reads as a liquid morph rather than a plain dissolve.
Each layer scales between 0.6 and 1 as it fades. That scale change adds a gravitational pull to the transition — the outgoing word seems to shrink and melt away while the incoming one grows into place — which makes the goo feel like it has mass rather than just fading.
The two layers only ever display two words at once, but JavaScript rotates through a longer WORDS list, assigning the next words to the layers while they're in their hidden phase. So words are swapped out of view, and you only ever see two words melting into each other, never a word changing in plain sight.
The goo filter merges shapes by blurring and thresholding, so it needs enough ink to blob convincingly. Large, bold, tightly-tracked letters have the mass to fuse during the transition; thin or small text doesn't have enough area for the blur to merge, and the melt looks weak.
Include the SVG filter once in a shared layout. Render the two word layers and keep the rotating word index in state or a ref, updating the layers' text on an interval set up in a mount effect with cleanup. The CSS keyframes and filter port directly. In Tailwind, apply the filter via an arbitrary filter:url(#gtGoo) value and animate opacity/scale with keyframes defined in the config.