Skip to content
animorio
IT
Back to the library

The surprise party

Hover, SVGGSAPMediumCompressed weight: Demo 7.0 KBGSAP 28 KBFreeDownload the zip

A headline with a round window in the middle of a line, and a mascot inside it. Little shapes hide all over the page: near the pointer they grow, turn twice and vanish. The «Click for a surprise» button starts the party: the window changes colour nine times, the mascot dances with its glasses on and every shape wakes three times.

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 surprise party</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/outfit@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/dm-serif-display@5.3.0/400-italic.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="bar">
    <a class="brand" href="#">Sprinkle &amp; Co.</a>
    <nav class="pill" aria-label="Sections">
      <a href="#">Cakes</a>
      <a href="#">Parties</a>
      <a href="#">Visit</a>
      <a class="pill__cta" href="#">Order a cake</a>
    </nav>
  </header>

  <main class="hero" data-hero>
    <!-- the shapes hide here: the script places them and wakes them near the pointer -->
    <div class="shapes" data-shapes aria-hidden="true"></div>

    <h1 class="title">
      <span class="title__line">Baking
        <!-- the round window with the mascot inside: it changes colour during the party -->
        <span class="window" data-window aria-hidden="true">
          <svg class="mascot" data-mascot viewBox="0 0 200 240">
            <g data-body>
              <!-- the paper cup -->
              <path d="M44 150h112l-12 78H56z" fill="#f7c868"/>
              <path d="M62 150l4 78M82 150l2 78M100 150v78M118 150l-2 78M138 150l-4 78" stroke="#e3ab45" stroke-width="7"/>
              <!-- the arms, each turning at its shoulder -->
              <g data-arm="left">
                <path d="M48 168c-16 2-26 10-32 22" fill="none" stroke="#e3ab45" stroke-width="9" stroke-linecap="round"/>
                <circle cx="15" cy="192" r="8" fill="#f7c868"/>
              </g>
              <g data-arm="right">
                <path d="M152 168c16 2 26 10 32 22" fill="none" stroke="#e3ab45" stroke-width="9" stroke-linecap="round"/>
                <circle cx="185" cy="192" r="8" fill="#f7c868"/>
              </g>
              <!-- the frosting, with its drips -->
              <path d="M28 156c-8-62 32-108 72-108s80 46 72 108c-6 8-14 4-18-4-4 10-14 12-20 2-6 10-18 10-24 0-6 10-18 10-24 0-6 10-16 8-20-2-4 8-12 12-18 4z" fill="#ff8fb3"/>
              <path d="M60 80c10-14 26-22 40-22" fill="none" stroke="#ffc2d6" stroke-width="7" stroke-linecap="round"/>
              <!-- sprinkles -->
              <g stroke-width="5" stroke-linecap="round">
                <path d="M66 70l8-4" stroke="#ffd23f"/>
                <path d="M130 66l7 6" stroke="#6a8cff"/>
                <path d="M146 100l4 8" stroke="#58c98f"/>
                <path d="M48 112l3-8" stroke="#ffffff"/>
                <path d="M112 54l8 2" stroke="#58c98f"/>
                <path d="M82 136l6-6" stroke="#ffd23f"/>
                <path d="M128 136l7 4" stroke="#ffffff"/>
              </g>
              <!-- the cherry -->
              <path d="M104 28c4-10 10-16 18-18" fill="none" stroke="#5b8a3c" stroke-width="4" stroke-linecap="round"/>
              <circle cx="100" cy="38" r="12" fill="#e5383b"/>
              <!-- the face -->
              <g data-eyes>
                <ellipse cx="80" cy="104" rx="9" ry="11" fill="#2a1d22"/>
                <ellipse cx="120" cy="104" rx="9" ry="11" fill="#2a1d22"/>
                <circle cx="83" cy="100" r="3" fill="#fff"/>
                <circle cx="123" cy="100" r="3" fill="#fff"/>
              </g>
              <path d="M86 124c8 8 20 8 28 0" fill="none" stroke="#2a1d22" stroke-width="5" stroke-linecap="round"/>
              <ellipse cx="66" cy="120" rx="8" ry="5" fill="#ff6f9c"/>
              <ellipse cx="134" cy="120" rx="8" ry="5" fill="#ff6f9c"/>
              <!-- the party glasses: they come down when the party starts -->
              <g data-glasses>
                <path d="M62 94h30c2 0 4 2 4 4v8c0 8-6 14-14 14h-6c-8 0-16-6-16-14v-8c0-2 1-4 2-4zM108 94h30c1 0 2 2 2 4v8c0 8-8 14-16 14h-6c-8 0-14-6-14-14v-8c0-2 2-4 4-4z" fill="#1d1b22"/>
                <path d="M96 100h8" stroke="#1d1b22" stroke-width="5"/>
                <path d="M68 100l8-4M114 100l8-4" stroke="#ffffff" stroke-width="3" stroke-linecap="round" opacity="0.7"/>
              </g>
            </g>
          </svg>
        </span>
        loud</span>
      <span class="title__line">party <em>cakes.</em></span>
    </h1>

    <footer class="hero__foot">
      <p class="hero__note" data-hint>Something hides around here. Move the pointer to find it.</p>
      <button class="surprise" type="button" data-surprise data-autoclic>Click for a surprise</button>
    </footer>
  </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.

38 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 surprise party” from Animorio and fit it into my site

What it does

The home page of an invented bakery making party cakes, Sprinkle & Co., on a cream background. In the middle the headline «Baking loud party cakes.»: between «Baking» and «loud» there is a dark round window, as big as a letter, and inside it a cupcake with a face rises from the bottom, puts on its glasses and waves. Around the headline eighteen shapes hide, stars, hearts, swirls, flowers, diamonds, bursts and sprinkles, in six colours: when the pointer comes within a hundred pixels of one, the shape grows while turning, makes two full turns and vanishes. Over the window the cupcake winks and points. Bottom right, the «Click for a surprise» button: the window runs through nine colours, the cupcake puts its glasses on and dances to the beat, jumping and raising its arms, and every shape wakes in random order, three times each.

How it works

The window in the headline

The window is an inline-block span 1.12 em wide and high, round and with hidden overflow, lowered by 0.16 em so it sits on the line like a letter. Inside it is the cupcake in SVG, wider than the window and resting below its edge, so you see it from the waist up.

The hidden shapes

The script places eighteen shapes in fixed spots around the headline, each with its drawing, colour and size from a seeded random, at scale 0. Waking is a GSAP timeline of SPIN seconds: in the first quarter it grows to 1 while turning half a turn, in the middle it makes a full turn at full size, in the last quarter it shrinks while turning the rest; every other one turns the other way.

The pointer

On every movement the script measures the distance between the pointer and each shape’s spot: under REACH pixels the shape wakes. While it is awake, and for half a second after, it does not wake again, so a pointer resting nearby does not keep it lit. Without a mouse every shape wakes by itself every AUTO seconds, each 0.3 seconds after the one before.

The party

The button builds a timeline: the window’s background runs through the colours in DISCO, one every STEP seconds, and at the end goes back to dark. Meanwhile every shape, in a shuffled order, wakes ROUNDS times: the i-th after GAP[0] · i seconds, and each round GAP[1] seconds after the one before. Everything goes through delayedCall, GSAP’s clock, and not the browser’s timers.

The mascot

The cupcake is a drawing with the body, arms, eyes and glasses in separate groups. The dance is built beat by beat, every half second: the body jumps 16 units while stretching and lands squashing, tilted 6 degrees to one side and the other, and the arms turn around the shoulders with svgOrigin, one up and one down. The eyes blink every two to four seconds.

Values to change

NameFileDefaultWhat it changes
REACHscript.js100How close the pointer must come to a hidden shape to wake it, in pixels.
SPINscript.js2The seconds a shape lives: it grows, turns and vanishes.
TURNSscript.js2How many turns it makes in that time.
COUNTscript.js18How many shapes hide on the page (24 at most).
COLORSscript.js['#6a8cff', '#ff7a45', '#1d1b22', '#ff8fb3', '#ffc93c', '#58c98f']The shapes’ colours.
DISCOscript.js['#ff8fb3', '#6a8cff', '#ffc93c', '#58c98f', '#ff7a45', '#b07cff', '#3fc6d6', '#ff5d5d', '#f7c868']The window’s colours during the party.
STEPscript.js0.45The seconds each colour of the party lasts.
ROUNDSscript.js3How many times each shape wakes during the party.
GAPscript.js[0.3, 2.5]During the party: the wait between one shape and the next, and between one round and the next, in seconds. Keep the second at least SPIN + 0.5: a round that finds the shape still awake is lost.
AUTOscript.js2.5Without a pointer (phones), every how many seconds each shape wakes by itself.

Try them in the Playground

When to use it

For an opening that should make people smile: sweets, games, parties, a creative studio with a character of its own. It wants a short headline and a mascot you recognise at once; on a serious page or a long read the shapes distract.

On phones

Without a pointer the shapes wake by themselves, one after the other, every two and a half seconds, and the button starts the party just as with a mouse. The headline goes to 15% of the window width and the menu keeps only the order button.

With reduced motion

The shapes do not grow or turn: they fade in and out. In the party the window changes colour at once and the mascot puts its glasses on without dancing; it does not rise from the bottom or wave.

Pitfalls

  • The shapes must live on GSAP’s clock, with delayedCall, and not on setInterval or a CSS animation: the preview bench and the recordings only stop the page’s clock.
  • A shape must be able to come back only half a second after it has gone, or a pointer resting nearby keeps it lit without a break.
  • The mascot’s arms turn around the shoulder with svgOrigin, in the drawing’s coordinates: a transformOrigin in percent refers to the group’s box, which changes while the arm moves.
  • If the party starts while the mascot is still saying hello, the entrance must be finished at once: it would end by taking the glasses off in the middle of the dance.
  • Between one round of the party and the next you need at least SPIN plus half a second: a shape stays awake for SPIN seconds and rests for half a second, and a call that finds it still lit is lost. The original site calls the shapes again every 2 seconds, so each one lights up twice instead of three times.

Libraries

GSAP 3.15.0, Outfit (font variabile) 5.3.0, DM Serif Display 5.3.0.

Compressed with gzip, the three demo files weigh 7.0 KB; the libraries: GSAP 28 KB.

Testing

Tested on 2 October 2026

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

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