
The dinosaur-bitten logo
Intro, SVG, Text
NewFree
A logo intro inside a soap bubble: a wand blows it in three breaths, the bubble breaks free with a jelly wobble and floats with the logo suspended inside, under the shifting colours of the film; then it pops in a shower of droplets and the logo stays, with a few drops sliding down it. In the Playground you type your own name or upload your own logo.
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 soap-bubble logo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/nunito@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="scena">
<!-- the stage: the script measures it, builds the wand, the bubble and the logo, and runs the story -->
<svg class="palco" data-stage role="img" aria-label="Opaline" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- the colours of the soap film: soft round patches that fade out at their edge -->
<radialGradient id="film-a"><stop offset="0" class="film-stop film-stop--a" /><stop offset="1" class="film-stop film-stop--a film-stop--via" /></radialGradient>
<radialGradient id="film-b"><stop offset="0" class="film-stop film-stop--b" /><stop offset="1" class="film-stop film-stop--b film-stop--via" /></radialGradient>
<radialGradient id="film-c"><stop offset="0" class="film-stop film-stop--c" /><stop offset="1" class="film-stop film-stop--c film-stop--via" /></radialGradient>
<radialGradient id="film-d"><stop offset="0" class="film-stop film-stop--d" /><stop offset="1" class="film-stop film-stop--d film-stop--via" /></radialGradient>
<radialGradient id="film-e"><stop offset="0" class="film-stop film-stop--e" /><stop offset="1" class="film-stop film-stop--e film-stop--via" /></radialGradient>
<!-- the thin rainbow band that runs round the edge of the film; the script turns it -->
<linearGradient id="rim-band" x1="0" y1="0" x2="1" y2="1" data-rim-band>
<stop offset="0" class="banda banda--a" />
<stop offset="0.25" class="banda banda--b" />
<stop offset="0.5" class="banda banda--c" />
<stop offset="0.75" class="banda banda--d" />
<stop offset="1" class="banda banda--a" />
</linearGradient>
<!-- the film is thicker at the bottom, where the soap runs down -->
<linearGradient id="rim-heavy" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="pesante pesante--via" />
<stop offset="0.62" class="pesante pesante--via" />
<stop offset="1" class="pesante" />
</linearGradient>
<!-- the film still in the ring, before it is blown -->
<linearGradient id="ring-film" x1="0" y1="0" x2="1" y2="0" data-ring-film-grad>
<stop offset="0" class="banda banda--b" />
<stop offset="0.35" class="banda banda--c" />
<stop offset="0.65" class="banda banda--a" />
<stop offset="1" class="banda banda--d" />
</linearGradient>
<!-- the outline of the bubble: the film, the rims and the reflections are cut by it -->
<clipPath id="film-clip"><path data-film-clip /></clipPath>
<!-- the hole that opens when it pops -->
<mask id="hole" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" data-hole-mask>
<rect fill="#fff" data-hole-all />
<circle fill="#000" cx="0" cy="0" r="0" data-hole />
</mask>
<!-- the swirls of colour are softened -->
<filter id="soften" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="6" data-soften />
</filter>
<!-- the last of the film on the letters: shown only where the logo is -->
<mask id="on-logo" maskUnits="userSpaceOnUse" style="mask-type: alpha" data-on-logo>
<use href="#logo-glyphs" />
</mask>
</defs>
<g data-world>
<!-- the wand: its stick, the back of the ring, the film in the ring and the air that rushes through it -->
<g data-wand-back></g>
<!-- the logo, floating inside the bubble -->
<g data-logo>
<g id="logo-glyphs" class="logo" data-glyphs></g>
<g mask="url(#on-logo)" data-sheen></g>
<g data-drips></g>
</g>
<!-- the bubble: 0 0 is its middle; the film, its rims and the reflections of a window -->
<g data-bubble>
<g clip-path="url(#film-clip)">
<g data-film>
<circle class="film-fondo" r="100" data-film-base />
<g class="film-colori" data-blobs></g>
<g class="film-vortici" filter="url(#soften)" data-swirls></g>
</g>
<path class="orlo-morbido" data-rim-soft />
<path class="orlo-pesante" stroke="url(#rim-heavy)" data-rim-heavy />
<path class="orlo-banda" stroke="url(#rim-band)" data-rim-band-path />
<g data-shine></g>
<circle class="strappo" r="0" data-tear />
</g>
<path class="orlo" data-rim-line />
</g>
<!-- the front of the ring, in front of the film -->
<g data-wand-front></g>
<g data-fx></g>
</g>
</svg>
<p class="nota">Click or tap to see it again</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.
26 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 soap-bubble logo” from Animorio and fit it into my siteThe stage is an SVG whose viewBox is as big as the window, so one unit is one pixel. The letters are measured on a canvas in the same typeface (measureText, actualBoundingBoxAscent for the true height) and the bubble is born from the logo: its radius is half the diagonal of the logo, shrunk to nine tenths, plus half a letter. The size is chosen so that the bubble fits in the window with the wand under it at the end of the blowing, on a computer and on a phone.
The bubble is a path rewritten every frame: two arcs for the round, two Bézier curves for the neck, which leave the circle on its tangent (the control point follows the circle's tangent) and come down to the ring, and half an ellipse below, the edge of the ring seen a little from above. Radius, distance of the ring, pinch of the neck and lean are numbers in a single object the timeline animates; when the bubble breaks free, the neck becomes a tail that snaps back with elastic.out. The jelly wobble is an opposite scale on x and y, turned in the chosen direction.
Inside the path, used as a clipPath, there are six patches with a radial gradient (full colour in the middle, transparent at the edge) in mix-blend-mode screen, going round the rim at different speeds; three swirls softened with feGaussianBlur; and three strokes of the same path: a light, wide one for the soft rim, one with a vertical gradient that is full only at the bottom (the soap running down), a thin one with a rainbow gradient turned by gradientTransform. On top, the reflection of an arched window with a thin cross, narrow and tall, its sides bent by the curve of the sphere, and an arc of light on the rim.
A mask with a black circle growing from a point on the rim opens the hole; an identical circle, clipped by the outline, is the torn edge that flashes. Each droplet leaves when the hole reaches it: with ease power1.in the radius grows with the square of the time, so the moment is the square root of its distance from where the tear began. The droplets fly outwards and away from the hole, then fall. The drops on the letters run down their stems: each letter is drawn on a canvas and the column with the longest run of ink is found.
The whole intro is one timeline, with the labels start, blow, detach, float, pop, reveal, rest and timeScale for the speed; the scene is redrawn once a frame from the timeline's onUpdate. The iridescence left on the letters is a group of coloured patches with an alpha mask holding a use of the logo. If IMAGE holds an address, the logo becomes that picture; in the Playground, next to the field, there is a button to upload a file, which goes into the code as a data: address.
| Name | File | Default | What it changes |
|---|---|---|---|
NAME | script.js | 'Opaline' | The logo as a word: it grows inside the bubble and stays when the bubble pops. |
IMAGE | script.js | '' | The logo as a picture: the address of a file, or upload it from your computer. If there is one, it takes the place of the word. |
SHIMMER | script.js | 1 | How lively the colours of the film are: 0.3 calm and pale, 2 bright and fast. |
HOVER | script.js | 1 | How many seconds the bubble floats with the logo inside before it pops. |
DROPS | script.js | 40 | How many droplets fly off when the bubble pops (plus a fine mist). |
DRIPS | script.js | 3 | How many drops land on the logo and slide down it (0 = none). |
SPEED | script.js | 1 | The speed of the whole animation: 2 is twice as fast, 0.5 half as fast. |
REST | script.js | 4 | How many seconds the logo stays on show before it starts again. |
LOOP | script.js | true | Whether a new bubble is blown after the rest. With false the logo stays, breathing gently. |
To present a logo with a light touch: the opening of a site for a cosmetics, soap or perfume brand, a toy shop, a party or a children's event, a studio with a gentle identity; a preview for a client, a loading screen, a social post. It works with a written wordmark and with a picture.
The same animation with the sizes adapted: the bubble is almost as wide as the screen and the wand comes in from the bottom right. A tap restarts it.
Nothing moves: the still bubble with the logo inside fades in, then fades away and leaves the logo, with its iridescence fading. If the animation starts again, the logo leaves with a fade too.
GSAP 3.15.0, Nunito (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 15 KB; the libraries: GSAP 28 KB.
Tested on 11 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.