Skip to content
animorio
IT
Back to the library

The soap-bubble logo

Intro, SVG, TextGSAPAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

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.

The code

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>

Playground

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

Or ask Claude Code for it

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 site

What it does

On a night-blue background an orange plastic bubble wand, a ring with a handle, comes in from below with the soap film still stretched inside it: it settles with an elastic wobble, a glint runs over the film and a drop falls from the ring. Then the ring is drawn slowly down and the film swells: first a dome, then a bubble growing in three breaths, swaying on the stretchy neck that holds it to the ring, while the air rushes through the ring and two tiny bubbles escape to the sides. Inside the bubble, as it grows, the letters of the logo of a made-up brand, Opaline, appear from the middle outwards. The neck pinches, stretches and lets go: the bubble jumps free with a jelly wobble, its tail snaps back, the wand drops out of the scene with a last flash of film. The bubble rises to the middle, sinks back a little and bounces softly on the air, then floats with the logo suspended inside: patches of magenta, cyan, gold, mint and violet flow over the film, a thread of rainbow runs round its edge, the rim is heavier at the bottom and an arched window is reflected at the top left. After a moment the film shivers, the colours race and the bubble pops: a hole opens from one point and runs across the whole film, the torn edge flashes, the droplets fly off one after the other as the hole reaches them and then fall, and a ring of light spreads out. The logo, free, gives a little jump and settles at full size; the iridescence of the film stays on the letters and slowly fades, and a few drops land on them, slide down their stems leaving a wet streak and drip off the bottom. After a few seconds the letters leave and a new bubble is blown. A click restarts it. A picture can take the place of the word.

How it works

One size

The 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 shape of the bubble

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.

The film

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.

The pop

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.

Direction and your logo

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.

Values to change

NameFileDefaultWhat it changes
NAMEscript.js'Opaline'The logo as a word: it grows inside the bubble and stays when the bubble pops.
IMAGEscript.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.
SHIMMERscript.js1How lively the colours of the film are: 0.3 calm and pale, 2 bright and fast.
HOVERscript.js1How many seconds the bubble floats with the logo inside before it pops.
DROPSscript.js40How many droplets fly off when the bubble pops (plus a fine mist).
DRIPSscript.js3How many drops land on the logo and slide down it (0 = none).
SPEEDscript.js1The speed of the whole animation: 2 is twice as fast, 0.5 half as fast.
RESTscript.js4How many seconds the logo stays on show before it starts again.
LOOPscript.jstrueWhether a new bubble is blown after the rest. With false the logo stays, breathing gently.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • GSAP reads the transform already written on an SVG element and turns it into its x and y: a drop placed with translate and then moved with gsap.set(x) lost its starting point. The drops keep their coordinates in the circles and GSAP only moves the group.
  • An SVG arc whose end point equals its start point is not drawn: when the bubble's tail has fully snapped back, the two tangent points meet at the bottom. The round is drawn with two arcs that pass through the top.
  • A white flash over the whole bubble at the pop looked like a glass disc left behind: the flash is only the spreading ring and the torn edge lighting up.
  • While blowing, the wand has no timing of its own: its position is worked out from the point of the ring in the bubble's shape (with the same scale and rotation), otherwise neck and ring came apart in the wobbles.
  • The drops on the letters slide only where there is ink: each letter is drawn on a canvas and the column with the longest solid run is chosen. Round letters without a stem (o, e) get no drops; with a picture from another site, which the canvas cannot read, evenly spaced columns are used.

Libraries

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.

Testing

Tested on 11 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

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.

All animations