Skip to content
animorio
IT
Back to the library

The lightning-struck logo

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

A logo preview in three acts: the letters are carried in by the wind, then a storm cloud with a face settles above them, turns dark, rains and thunders, and a zigzag bolt chars one letter, which starts smoking; a second bolt makes another letter jump and land crooked. Then a little sun comes out and dries everything. 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 lightning-struck logo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/big-shoulders-display@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="scena">
    <!-- the stage: the script measures it, writes the logo in it and moves the cloud and the sun -->
    <svg class="palco" data-stage role="img" aria-label="Stormline" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <!-- the cloud is a heap of puffs: drawn three times (outline, body, dark body), so the outline is only outside -->
        <g id="puffs" data-puffs>
          <ellipse cx="0" cy="14" rx="122" ry="58" />
          <circle cx="-82" cy="-8" r="50" />
          <circle cx="-26" cy="-44" r="62" />
          <circle cx="44" cy="-38" r="55" />
          <circle cx="100" cy="-4" r="46" />
          <circle cx="-126" cy="22" r="34" />
          <circle cx="130" cy="24" r="32" />
          <circle cx="-84" cy="54" r="30" />
          <circle cx="-28" cy="60" r="32" />
          <circle cx="34" cy="60" r="31" />
          <circle cx="90" cy="50" r="30" />
        </g>
        <!-- whatever is drawn inside the cloud stays inside it -->
        <mask id="in-cloud" maskUnits="userSpaceOnUse" x="-260" y="-220" width="520" height="420" style="mask-type: alpha">
          <use href="#puffs" fill="#fff" />
        </mask>
      </defs>

      <g data-world>
        <!-- the sky behind everything: dark with the storm, white with a flash, warm with the sun -->
        <rect class="cielo-buio" data-dark-sky />
        <rect class="lampo" data-flash />
        <rect class="luce-sole" data-sunlight />
        <g data-wind></g>
        <g data-ground>
          <ellipse class="ombra-nuvola" data-cloud-shadow />
          <ellipse class="pozza" data-puddle />
          <ellipse class="pozza-lucido" data-puddle-shine />
        </g>
        <g data-ripples></g>
        <g id="logo" data-logo></g>
        <g data-smoke></g>
        <g data-rain></g>
        <g data-bolts></g>

        <!-- the cloud: drawn around 0 0, the bottom of its belly is at y 92 -->
        <g data-cloud-place transform="translate(-9999 -9999)">
          <g data-cloud-float>
            <g data-cloud-body>
              <use href="#puffs" class="nuvola-bordo" />
              <use href="#puffs" class="nuvola" />
              <g mask="url(#in-cloud)">
                <ellipse class="nuvola-pancia" cx="0" cy="98" rx="178" ry="50" />
                <path class="nuvola-ricciolo" d="M-64 66Q-60 50 -44 46M0 70Q2 54 18 50M60 64Q64 50 78 46M-112 40Q-116 26 -104 16M108 42Q114 28 104 18M-62 -28Q-70 -42 -60 -54Q-50 -62 -42 -54M24 -64Q30 -80 46 -80Q60 -78 62 -66" />
                <path class="nuvola-lucido" d="M-118 4Q-114 -26 -90 -38M-70 -62Q-56 -96 -18 -102M30 -84Q56 -88 76 -70" />
              </g>
              <!-- the angry cloud: the same puffs, darker, fading in over the light ones -->
              <g class="buio" data-cloud-dark>
                <use href="#puffs" class="nuvola-scura" />
                <g mask="url(#in-cloud)">
                  <ellipse class="nuvola-pancia-scura" cx="0" cy="98" rx="178" ry="50" />
                  <path class="nuvola-ricciolo-scuro" d="M-64 66Q-60 50 -44 46M0 70Q2 54 18 50M60 64Q64 50 78 46M-112 40Q-116 26 -104 16M108 42Q114 28 104 18M-62 -28Q-70 -42 -60 -54Q-50 -62 -42 -54M24 -64Q30 -80 46 -80Q60 -78 62 -66" />
                </g>
              </g>
              <!-- the face -->
              <ellipse class="guancia" cx="-68" cy="24" rx="15" ry="9.5" data-cheek-l />
              <ellipse class="guancia" cx="68" cy="24" rx="15" ry="9.5" data-cheek-r />
              <ellipse class="occhio" cx="-36" cy="-6" rx="16" ry="19" />
              <ellipse class="occhio" cx="36" cy="-6" rx="16" ry="19" />
              <g data-pupils>
                <circle class="iride" cx="-37" cy="-4" r="9.5" />
                <circle class="pupilla" cx="-37" cy="-4" r="5" />
                <circle class="riflesso" cx="-40.5" cy="-8" r="2.4" />
                <circle class="iride" cx="35" cy="-4" r="9.5" />
                <circle class="pupilla" cx="35" cy="-4" r="5" />
                <circle class="riflesso" cx="31.5" cy="-8" r="2.4" />
              </g>
              <g data-lid-l>
                <ellipse class="palpebra" cx="-36" cy="-6" rx="18.5" ry="21.5" />
                <ellipse class="palpebra-scura buio" cx="-36" cy="-6" rx="18.5" ry="21.5" />
              </g>
              <g data-lid-r>
                <ellipse class="palpebra" cx="36" cy="-6" rx="18.5" ry="21.5" />
                <ellipse class="palpebra-scura buio" cx="36" cy="-6" rx="18.5" ry="21.5" />
              </g>
              <path class="sopracciglio" d="M-58 -38Q-40 -48 -18 -36" data-brow-l />
              <path class="sopracciglio" d="M58 -38Q40 -48 18 -36" data-brow-r />
              <path class="bocca-linea" d="M-18 42Q0 30 18 42" data-mouth-frown />
              <ellipse class="bocca" cx="0" cy="40" rx="9" ry="11" data-mouth-o />
              <path class="bocca" d="M-24 32Q0 60 24 32Q0 40 -24 32Z" data-mouth-grin />
              <g data-sparks></g>
            </g>
          </g>
        </g>

        <!-- the little sun that dries everything: drawn around 0 0 -->
        <g data-sun-place transform="translate(-9999 -9999)">
          <g data-sun-body>
            <g data-sun-rays></g>
            <circle class="sole" cx="0" cy="0" r="50" />
            <path class="sole-lucido" d="M-36 -18Q-30 -36 -12 -42" />
            <ellipse class="sole-guancia" cx="-30" cy="14" rx="9" ry="5.5" />
            <ellipse class="sole-guancia" cx="30" cy="14" rx="9" ry="5.5" />
            <ellipse class="occhio occhio--sole" cx="-17" cy="-6" rx="9" ry="11" />
            <ellipse class="occhio occhio--sole" cx="17" cy="-6" rx="9" ry="11" />
            <g data-sun-pupils>
              <circle class="iride iride--sole" cx="-18" cy="-4" r="6" />
              <circle class="pupilla" cx="-18" cy="-4" r="3.3" />
              <circle class="riflesso" cx="-20" cy="-6.6" r="1.6" />
              <circle class="iride iride--sole" cx="16" cy="-4" r="6" />
              <circle class="pupilla" cx="16" cy="-4" r="3.3" />
              <circle class="riflesso" cx="14" cy="-6.6" r="1.6" />
            </g>
            <ellipse class="sole-palpebra" cx="-17" cy="-6" rx="10.5" ry="12.5" data-sun-lid-l />
            <ellipse class="sole-palpebra" cx="17" cy="-6" rx="10.5" ry="12.5" data-sun-lid-r />
            <path class="sole-bocca" d="M-15 14Q0 30 15 14Q0 20 -15 14Z" />
          </g>
        </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.

42 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 lightning-struck logo” from Animorio and fit it into my site

What it does

On light paper the logo of a made-up brand, Stormline, arrives in a tall, narrow, very heavy typeface: a gust of wind carries it in from the left, with wind lines that curl at their ends, and the letters slide in leaning back, stop tipping forward and straighten up with an elastic wobble. A grey cloud with a face drifts in from the right, boiling at its edges and gently bobbing: it stops above the logo with a squash, blinks, looks down, frowns and puffs out its cheeks. Then it turns dark, and so does the sky: it starts to rain, the drops splash on the letters and on the floor, where a puddle opens with rings on it. Two thunderclaps: the cloud booms with its mouth open, the stage shakes and the whole background lights up for a moment. The cloud swells, sparks crackle between its cheeks, and a zigzag bolt, drawn in a tenth of a second, strikes one letter: a white flash, then the letter is charred, black where it was hit and scorched further down, with blackened edges and cracks of orange embers that slowly die; sparks fly, the letter squashes and slumps a little, and smoke rises in puffs. The cloud moves along and a smaller bolt makes another letter jump, spin and land crooked on one corner, among the splashes. Pleased with itself, the cloud laughs, huffs and drifts off to the left, dripping and growing lighter. The logo stays like that: the letters smoke, the embers slowly wake up again, water runs down the letters into the puddle. After a few seconds a little smiling sun comes out, the light turns warm, the puddle steams away, the burn fades, the letters straighten up with a hop and the story starts again. A click restarts it from the beginning. A picture can take the place of the word: the rain, the bolts and the burn work there too.

How it works

A stage to 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 that gives a single size for everything, top to bottom: the cloud, the room the bolt falls through, the logo, the floor. On a tall screen the cloud is bigger and higher, so the bolt travels further.

Where the rain lands

The letters are also drawn on a canvas and, column by column, the first solid pixel from the top is read: that is where a drop splashes, and everything else falls to the floor and makes a ring in the puddle. The drops start from the cloud’s belly, wherever it is at that moment: its moves are written in a list with their ease, and cloudX(t) tells where it is at any time.

The cloud

It is a heap of circles in a group inside defs, drawn three times with use: once with a wide outline, once in the light colour, once in the dark one that shows up when it gets angry. That way the outline is only on the outside and the edges can boil: changing the circles’ radius is enough, and the three copies follow. The belly and the curls sit inside a mask made of the same heap. Eyes with iris, highlight and eyelid, brows, cheeks and three mouths turn or scale on their own point, worked out with getBBox.

The bolt

A zigzag from under the cloud to the highest point of the letter, with one or two branches ending in the air, drawn four times: a wide transparent glow, a dark outline, the yellow and a white core. Every line has pathLength 1 and is traced by taking stroke-dashoffset from 1 to 0 in a tenth of a second. At the same moment the background flashes, the stage shakes and a star bursts on the letter.

The burnt letter

The struck letter has a copy of itself as an alpha mask and, inside it, over the logo colour, a radial gradient from the point it was hit (black, then brown, then transparent), the outline of the letter in thick black, which the mask cuts in half so only the inner edge is left, and cracks of embers in orange and yellow. A light rectangle in the same mask is the flash on the letter. The letter slumps with scaleY and skewX from its foot; the other one jumps, spins and lands at the angle that puts its lowest corner on the floor.

Direction and your logo

The whole story is one timeline, with timeScale for the speed: every letter has three groups one inside the other, for the wind, the jump and the burn, so the transforms never get in each other’s way. At the end the sun dries everything and the scene is rebuilt from the «arrive» label, with new rain and new bolts every time. If IMAGE holds an address the logo becomes that picture: a single piece, hit at a third of its width and made to jump by the second bolt.

Values to change

NameFileDefaultWhat it changes
NAMEscript.js'Stormline'The logo as a word: every letter is a piece the lightning can hit.
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.
STRUCKscript.js2The letter the big bolt chars, counting from 0 (spaces count). A picture is hit at a third of its width.
BOLTSscript.js2How many bolts fall, from 1 to 3: the first one burns a letter, the others make one jump and land crooked.
RAINscript.js26How much rain, in drops per second. With 0 the storm is dry and there is no puddle.
CLOUDscript.js2.6How wide the cloud is, in letter heights.
SPEEDscript.js1The speed of the whole story: 2 is twice as fast, 0.5 half as fast.
RESTscript.js4How many seconds the logo stays scorched and smoking before the sun comes out.
LOOPscript.jstrueWhether the sun dries everything and the story starts again. With false the logo stays burnt and keeps smoking.

Try them in the Playground

When to use it

To present a logo in a way nobody forgets: a preview for a client, the opening of a site or a video, a 404 page or a loading screen with a sense of humour, a social post, a brand about weather, energy or electricity. It works with a written wordmark and with a picture.

On phones

The same story, with the sizes adapted: on a tall screen the cloud is bigger and sits higher, so the bolt has a longer way to fall. A tap restarts it.

With reduced motion

Nothing moves: the logo fades in, then the dark cloud with the rain standing still, then a bolt that appears and disappears, the burn and the puddle, and the cloud fades away. If the story starts again, the sun and the drying are fades too.

Pitfalls

  • A cloud made of overlapping circles cannot get an outline on each circle, or all the lines stay inside it: the heap is drawn twice with use, first with a wide dark stroke and then filled on top, and the outline is left only on the outside.
  • An element whose class sets its colour cannot be recoloured from a use: the cloud’s circles in defs have no colour at all, so each use gives its own (outline, light, dark, mask).
  • A line with pathLength 1 and stroke-dasharray «1 1» leaves a dot at its start when it is rubbed out with dashoffset -1, because of the round cap: with «1 2» the gap is long enough and the dot is gone.
  • The yellow bolt disappeared right at the flash, when the background turns light: it has a dark outline like the cloud’s, between the glow and the yellow.
  • The sun waiting off screen on the right peeked in for a moment when the stage shook: it starts further away, beyond the tips of its rays.
  • A picture from another site cannot be read on a canvas (getImageData throws): then the rain splashes on the top edge of its box.
  • A letter turned around its middle sinks a corner into the floor: after the jump it rises by just enough, half its width times the sine of the angle plus half its height times the cosine, minus half its height.
  • The sparks between the cheeks, drawn as one zigzag line, looked like a gritted mouth: they became short discharges jumping off the cheeks.

Libraries

GSAP 3.15.0, Big Shoulders Display (font variabile) 5.3.0.

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

Testing

Tested on 10 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