
Marquee that speeds up with scroll
Scroll, Text, Hover
Free
A sweet shop's title made of pink bubblegum, puffy and glossy: under the pointer the letters stick and stretch into a strand that pulls and snaps, then spring back. Now and then a letter blows a bubble that grows, trembles and pops; a click pops a big one.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The bubblegum title</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fredoka@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="shop">
<header class="shop__top">
<p class="shop__brand">Mollie’s Sweet Shop</p>
<p class="shop__line">Pick and mix, weighed by hand</p>
</header>
<!-- the title is drawn in the svg below; this one is for screen readers and search engines -->
<h1 class="shop__title" data-title>Chewy</h1>
<!-- one svg as big as the window: the gum (letters, strands, shreds) goes through a single filter that melts it
together and lights it; the bubbles sit on top, outside the filter, because they are thin and see-through -->
<svg class="gum" data-gum aria-hidden="true">
<defs>
<filter id="gum-goo" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" data-goo>
<feGaussianBlur in="SourceGraphic" stdDeviation="6" result="blur" data-blur />
<feColorMatrix in="blur" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 24 -11" result="goo" />
<feGaussianBlur in="goo" stdDeviation="9" result="height" data-height />
<feSpecularLighting in="height" surfaceScale="20" specularConstant="1" specularExponent="38" lighting-color="#ffffff" result="spec" data-spec>
<feDistantLight azimuth="225" elevation="52" />
</feSpecularLighting>
<feComposite in="spec" in2="goo" operator="in" result="shine" />
<feDiffuseLighting in="height" surfaceScale="20" diffuseConstant="1.18" lighting-color="#ffffff" result="light" data-diffuse>
<feDistantLight azimuth="225" elevation="58" />
</feDiffuseLighting>
<feComposite in="goo" in2="light" operator="arithmetic" k1="0.6" k2="0.45" k3="0" k4="0" result="shaded" />
<feComposite in="shine" in2="shaded" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="lit" />
<feGaussianBlur in="goo" stdDeviation="10" result="soft" data-shadow-blur />
<feOffset in="soft" dx="0" dy="12" result="drop" data-shadow-offset />
<feFlood flood-color="#a3245a" flood-opacity="0.26" result="tone" data-shadow-tone />
<feComposite in="tone" in2="drop" operator="in" result="shadow" />
<feMerge>
<feMergeNode in="shadow" />
<feMergeNode in="lit" />
</feMerge>
</filter>
<radialGradient id="gum-film" cx="0.42" cy="0.38" r="0.66">
<stop offset="0" class="film-in" />
<stop offset="0.72" class="film-mid" />
<stop offset="1" class="film-out" />
</radialGradient>
</defs>
<g data-world>
<g class="gum__body" filter="url(#gum-goo)" data-body></g>
<g class="gum__bubbles" data-bubbles></g>
</g>
</svg>
<p class="shop__hint" data-hint>Move over the letters to stretch the gum. Click to blow a big bubble.</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
19 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The bubblegum title” from Animorio and fit it into my siteThe letters are plain SVG text, one per element, with an outline in the same colour that fattens them. Everything that is gum (letters, strands, flaps, drops) sits in a group with a single filter. A feGaussianBlur and a feColorMatrix that multiplies the alpha by 24 and takes away 11 make the goo effect: nearby pieces melt together and corners round off. Then the same result, blurred, becomes a height map: feSpecularLighting gives the glossy highlight, feDiffuseLighting the shade on the sides, and a feComposite arithmetic mixes them with the pink. Below, the same shape blurred and moved down makes the shadow.
The word is measured on a canvas in the same typeface (measureText, with actualBoundingBox for each letter's true outline) and the size is chosen so that it fits the window. Everything else is counted in font sizes: the filter's blur, the relief, the thickness of strands and flaps, the reach, the bubbles. The SVG's viewBox is as big as the window, so one unit is one pixel and the filter's numbers stay right.
Each letter has a state (shift, stretch along a direction, squash on the baseline, tilt) that becomes a matrix, written as a transform. When the pointer enters a letter the hook point is fixed; on every frame the strand is drawn as a polygon along a quadratic curve, from the hook (moved by the same matrix) to the pointer: wide at the base, a waist that thins with the length, a blob on the tip, and the control point lowered by the square of the tension, so that it sags. Meanwhile the letter stretches towards the pointer.
Past its reach the strand snaps: it becomes a loose strand that goes back into the letter in 0.34 seconds with power3.in, while the letter springs back with elastic.out (the stretch dips below zero and the letter squashes sideways before it stops). A drop stays where the pointer was and falls with gravity, shrinking: through the filter's threshold it seems to soak away. The two neighbouring letters rock a little, and the letter stays free for half a second before it can stick again.
The bubble sits outside the filter, on top of the letters: a circle with a see-through pink radial gradient, a thin rim and two white arcs of highlight; a neck of gum, inside the filter, ties it to the letter. A timeline blows it in three breaths, then makes it tremble with two sines at different speeds on scaleX and scaleY. When it pops the bubble disappears and the flaps start in its place: curved strokes inside the filter, the root near the middle and the loose edge pulling in and then falling. A moment later they are sucked into the middle of the letter, which squashes again. Bubbles come by themselves with a random delayedCall; a click blows a big one on the nearest letter, or pops the one it touches.
| Name | File | Default | What it changes |
|---|---|---|---|
TEXT | script.js | 'Chewy' | The title, one word: it sizes itself to fit the window. |
REACH | script.js | 2.2 | How far a strand stretches before it snaps, in letter heights. |
SPRING | script.js | 0.3 | How the letters spring back: lower, and they wobble more before stopping. |
PUFF | script.js | 1 | How puffed up the letters are: higher, and they get fatter and melt together more. |
GLOSS | script.js | 1 | How shiny the gum is (0 = matt). |
BUBBLE | script.js | 1 | How big the bubbles grow. |
EVERY | script.js | 4.5 | How many seconds, more or less, between one bubble and the next. |
For a title that begs to be touched: the site of a sweet shop or an ice-cream parlour, a gum or soft-drink brand, a kids' party page, a game, a summer event. It works with a short, big word, on its own in the middle.
The same animation with the sizes adapted: the word is nearly as wide as the screen and everything (strands, bubbles, flaps) is counted from its size. Drag a letter with a finger to stretch it; a tap blows the big bubble. Page scrolling is off, so the finger pulls the gum.
Nothing moves: the word fades in, already in place, the letters do not stretch and the bubbles fade in and out, already blown, without popping. A click brings the big bubble in the same way.
GSAP 3.15.0, Fredoka (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 10 KB; the libraries: GSAP 28 KB.
Tested on 10 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.