Skip to content
animorio
IT
Back to the library

The dinosaur-bitten logo

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

A logo preview in three acts: the letters drop and land with a squash, then a dinosaur walks in from the right, roars and bites off the end of the logo, which bleeds in thick drips; a stomp cracks a letter in two. 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 dinosaur-bitten logo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/unbounded@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 dinosaur -->
    <svg class="palco" data-stage role="img" aria-label="Brambly" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <!-- the bite: everything white stays, the black circles are the hole -->
        <mask id="bite" maskUnits="userSpaceOnUse" data-bite-mask>
          <rect fill="#fff" data-bite-full />
          <g fill="#000" data-hole></g>
        </mask>
        <!-- the wound shows only where there is still logo -->
        <mask id="on-logo" maskUnits="userSpaceOnUse" style="mask-type: alpha" data-on-logo>
          <use href="#logo" />
        </mask>
        <!-- the piece of logo that ends up in the mouth -->
        <clipPath id="chunk-cut" data-cut></clipPath>
        <radialGradient id="wound-fill" gradientUnits="userSpaceOnUse" data-wound-fill>
          <stop offset="0" class="ferita-scura" />
          <stop offset="0.66" class="ferita-scura" />
          <stop offset="0.74" class="ferita" />
          <stop offset="1" class="ferita ferita--via" />
        </radialGradient>
        <!-- the drips melt into each other like a thick liquid -->
        <filter id="goo" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" data-goo>
          <feGaussianBlur in="SourceGraphic" stdDeviation="5" data-goo-blur />
          <feColorMatrix values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 22 -9" />
        </filter>
        <!-- the dinosaur's body and tail, to keep the belly, the stripes and the spots inside them -->
        <clipPath id="dino-body-clip">
          <path d="M176 64C192 88 214 100 246 104C278 108 300 118 318 128L336 170L316 222C296 252 246 262 200 254C156 246 128 210 126 168C126 140 132 116 146 98Z" />
        </clipPath>
        <clipPath id="dino-tail-clip">
          <path d="M296 126C340 122 400 108 462 80C456 110 424 148 384 176C360 194 334 212 300 230Z" />
        </clipPath>
      </defs>

      <g data-world>
        <g data-ground></g>
        <g id="logo" data-logo></g>
        <g mask="url(#on-logo)"><circle class="ferita-disco" fill="url(#wound-fill)" data-wound /></g>
        <g class="sangue" filter="url(#goo)" data-blood></g>
        <g data-shine></g>

        <!-- the dinosaur: drawn facing left, the point between its feet is 0 0 -->
        <g data-dino-place>
          <ellipse class="dino-ombra" cx="0" cy="2" rx="120" ry="10" data-dino-shadow />
          <g data-dino-flip>
            <g data-dino-body>
              <g transform="translate(-250 -300)">
                <!-- the far leg, darker, behind everything -->
                <g data-leg-back>
                  <path class="dino-lontano" d="M258 190C252 160 302 156 318 186C330 210 318 238 298 246L294 280L304 284C313 288 313 300 304 300L250 300C240 300 238 290 248 287L270 282L272 246C258 238 260 212 258 190Z" />
                  <path class="unghia" d="M250 300L239 302L248 294ZM262 300L252 303L260 295Z" />
                </g>
                <!-- the tail: its spikes behind it, its stripes and spots inside it -->
                <g data-tail>
                  <path class="dino-cresta" d="M324.7 126Q332.6 114.8 338.5 108Q339.1 117.8 343.3 126ZM355.9 118Q362.8 107.8 367.9 102Q368.4 110.5 372.1 118ZM386.2 108Q392 99 396.3 94Q396.8 101.2 399.8 108ZM415.4 98Q420.2 90 423.7 86Q424.1 91.8 426.6 98ZM439.7 89Q443.3 82.2 446.1 79Q446.4 83.5 448.3 89Z" />
                  <path class="dino" d="M296 126C340 122 400 108 462 80C456 110 424 148 384 176C360 194 334 212 300 230Z" />
                  <g clip-path="url(#dino-tail-clip)">
                    <path class="dino-pancia" d="M300 232C334 214 362 196 386 178C420 152 452 116 470 80L470 260L300 260Z" />
                    <path class="dino-macchia" d="M352 132C360 126 372 126 374 132C372 138 358 140 352 132ZM392 118C398 113 408 113 409 118C407 123 396 124 392 118ZM424 104C429 100 436 100 437 104C435 108 427 109 424 104Z" />
                  </g>
                </g>
                <!-- the spikes along the back, half hidden by the body -->
                <path class="dino-cresta" d="M185.9 87Q192.8 76.8 197.9 71Q198.4 79.5 202.1 87ZM207.5 99Q216.4 86.7 223.1 79Q223.8 90 228.5 99ZM233.2 106Q243.2 92.5 250.7 84Q251.5 96.3 256.8 106ZM261.8 111Q271.3 98.1 278.4 90Q279.1 101.7 284.2 111ZM289.1 120Q297.5 108.2 303.8 101Q304.5 111.4 308.9 120Z" />
                <!-- the throat swells when it swallows -->
                <circle class="dino" cx="150" cy="110" r="0" data-gulp />
                <!-- body and neck in one piece; the outline is drawn apart, so that it stops where the tail starts -->
                <path class="dino dino--pieno" d="M176 64C192 88 214 100 246 104C278 108 300 118 318 128L336 170L316 222C296 252 246 262 200 254C156 246 128 210 126 168C126 140 132 116 146 98Z" />
                <g clip-path="url(#dino-body-clip)">
                  <path class="dino-pancia" d="M128 150C140 206 186 244 250 252C276 255 300 248 318 234L318 300L100 300L100 150Z" />
                  <path class="dino-righe" d="M124 174Q137 179 148 173M130 198Q147 205 162 198M143 220Q163 229 180 221M164 238Q187 247 207 240M196 250Q220 257 244 250" />
                  <path class="dino-macchia" d="M226 118C234 111 248 112 250 119C247 126 232 127 226 118ZM260 126C266 121 276 122 277 127C275 132 264 133 260 126ZM204 104C209 100 217 101 218 105C216 109 208 110 204 104ZM288 138C293 134 300 135 301 139C299 143 292 144 288 138Z" />
                  <path class="dino-lucido" d="M196 96C218 110 252 116 296 126" />
                </g>
                <path class="dino-linea" d="M176 64C192 88 214 100 246 104C278 108 300 118 318 128M316 222C296 252 246 262 200 254C156 246 128 210 126 168C126 140 132 116 146 98" />
                <!-- the far arm, darker, over the chest -->
                <g data-arm-back>
                  <path class="braccio-bordo" d="M174 190Q160 200 156 212Q148 210 140 206" />
                  <path class="braccio braccio--lontano" d="M174 190Q160 200 156 212Q148 210 140 206" />
                  <path class="unghia" d="M136 202L129 201L135 207ZM137 208L131 211L138 211Z" />
                </g>
                <!-- the head: it turns on the neck; the inside of the mouth, the piece it bites, the jaw, then the skull -->
                <g data-head>
                  <g data-mouth>
                    <path class="bocca" d="M158 104L64.5 98L64.5 182.4Z" />
                    <path class="lingua" d="M152 110C132 114 104 124 86 142C82 148 92 151 99 146C114 135 134 124 154 117Z" />
                  </g>
                  <g data-chunk-slot></g>
                  <g data-jaw>
                    <path class="dente" d="M42 106L47 93L53 106ZM58 106L63 94L69 106ZM74 106L79 94L85 106ZM90 106L95 94L101 106ZM106 106L111 95L117 106ZM122 106L127 96L132 106Z" />
                    <path class="dino" d="M158 104L36 104C25 104 20 114 28 122C44 136 104 140 144 132C166 128 170 112 158 104Z" />
                    <path class="dino-righe" d="M48 124Q90 132 136 124" />
                  </g>
                  <path class="dente" d="M34 100L39 113L45 100ZM50 100L55 113L61 100ZM66 100L71 113L77 100ZM82 100L87 113L93 100ZM98 100L103 113L109 100ZM114 100L119 112L125 100ZM130 100L135 111L141 100Z" />
                  <path class="dino" d="M182 82C184 56 168 38 140 34C128 26 108 24 96 32C70 32 36 42 18 62C8 74 10 94 24 100L158 104C176 104 184 96 182 82Z" />
                  <path class="dino-macchia" d="M146 50C151 45 160 46 161 51C159 56 150 57 146 50ZM164 62C168 59 174 60 174 64C172 68 166 68 164 62ZM58 46C62 43 68 43 69 46C67 50 61 50 58 46Z" />
                  <path class="dino-lucido" d="M30 58C48 44 72 38 92 37" />
                  <path class="dino-scuro" d="M26 60C29 56 36 57 37 60C35 64 28 64 26 60Z" />
                  <ellipse class="guancia" cx="142" cy="88" rx="13" ry="7" data-blush />
                  <ellipse class="orbita" cx="114" cy="60" rx="19" ry="16" />
                  <circle class="occhio" cx="112" cy="60" r="13" />
                  <g data-pupil>
                    <circle class="iride" cx="107.5" cy="61" r="8" />
                    <circle class="pupilla" cx="106.5" cy="61" r="4.6" />
                    <circle class="riflesso" cx="104" cy="57.6" r="2.4" />
                  </g>
                  <ellipse class="palpebra" cx="112" cy="60" rx="15.6" ry="15.6" data-lid />
                  <path class="ciglio" d="M95 42Q112 33 131 42" data-brow />
                </g>
                <!-- the near arm, in front of the chest -->
                <g data-arm>
                  <path class="braccio-bordo" d="M166 184Q151 194 146 207Q137 205 128 199" />
                  <path class="braccio" d="M166 184Q151 194 146 207Q137 205 128 199" />
                  <path class="unghia" d="M124 195L117 194L123 200ZM125 201L119 204L126 204Z" />
                </g>
                <!-- the near leg, with its thigh -->
                <g data-leg-front>
                  <path class="dino" d="M182 206C176 176 226 166 244 194C258 216 246 246 224 252L220 282L232 286C241 290 241 300 232 300L176 300C166 300 164 290 174 287L198 282L198 250C186 242 184 222 182 206Z" />
                  <path class="dino-righe" d="M196 220C204 236 222 242 238 232M200 284L218 284" />
                  <path class="unghia" d="M176 300L165 302L174 294ZM188 300L178 303L186 295Z" />
                </g>
              </g>
            </g>
          </g>
        </g>

        <g data-crumbs></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.

25 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 dinosaur-bitten logo” from Animorio and fit it into my site

What it does

On bone-coloured paper the logo of a made-up brand, Brambly, arrives in a wide, jet-black typeface: the letters drop from above one after the other, squash as they touch the line and bounce back like rubber. The ground starts to shake, the logo shuffles aside and a green tyrannosaur walks in from the right, with heavy steps that make the letters hop. It stops, sniffs, roars (the letters bend back as if in a wind), then winds up and bites off the end of the logo: the letter is left with a round hole with tooth marks, the edge turns red and thick drips start to run, falling to the floor into a puddle. The dinosaur chews, spits out crumbs of letter, swallows happily and stamps a foot: the stomp makes the logo jump and one letter cracks in a zigzag, splits in two and both halves fall to the floor. It realises the mess, eyes wide, turns round and runs off. The logo stays like that, bitten and dripping, while the dinosaur pokes its head back in from the edge for a look; after a few seconds the logo heals (the blood goes back up, the hole closes, the broken letter jumps back into place) and the story starts again. A click restarts it from the beginning. A picture can take the place of the word: the bite, the blood and the crack 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: logo, bite and dinosaur always sit side by side. On a tall screen the dinosaur is a little bigger and, once stopped, shows only its head and chest: the rest stays past the edge.

The bite

The bite is an SVG mask: a white rectangle and, in black, a circle with seven small circles on its left edge, the tooth marks. It sits on every bitten letter and, with maskUnits userSpaceOnUse, follows the letter when it moves. The same shape, as a clipPath, cuts out a copy of the bitten piece that goes inside the dinosaur’s head: it gets the inverse of the head’s transform (getCTM), so it starts exactly where it was bitten and then follows the mouth as it chews.

The blood

The wound is a radial gradient that spreads from the edge of the hole, shown only where there is still logo thanks to an alpha mask holding a use of the logo. The drips are a rectangle and a circle growing downwards, under a filter that makes them run like a thick liquid (a blur and then a matrix that hardens the alpha). Where they start is found by drawing the bitten letters on a canvas and reading the pixels along the edge of the bite. The drops fall with power2.in and each one widens the puddle.

The crack

The letter that breaks has two copies, each cut by a clipPath that follows the same zigzag, and the zigzag drawn on top in the colour of the paper: it is traced with stroke-dashoffset. Until it cracks the whole letter is shown, because two halves side by side leave a thin line. Then each half turns around its outer bottom corner and falls to the floor with bounce.out.

The dinosaur

It is drawn only once in the page, in pieces and with an outline: legs with thighs and claws, tail with spikes and spots, little arms, striped belly, head with the jaw, the tongue, the yellow eye, the eyelid and the brow. Each piece turns around its own joint: a point of the drawing (the hip, the shoulder, the hinge of the jaw) that the script turns into percentages of the piece’s box with getBBox. Once in the mouth, the bitten piece slides to the tip of the snout and stays held between the teeth while it chews. The walk is a nested timeline that repeats; place, size and facing go into one object written as a transform attribute. The inside of the mouth is a triangle stretched by the cosine and sine of the opening, so its corner stays behind the tip of the jaw.

Direction and your logo

The whole story is one timeline, with timeScale for the speed. At the end the logo heals and the scene is rebuilt from the «arrive» label, with new drips every time. If IMAGE holds an address, the logo becomes that picture: a single piece, bitten on the right and cracked at four tenths of its width. In the Playground, next to the field, there is a button to upload a file from your computer, which goes into the code as a data: address.

Values to change

NameFileDefaultWhat it changes
NAMEscript.js'Brambly'The logo as a word: every letter is a piece the dinosaur can bite or break.
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.
BREAKSscript.js2The letter that cracks, counting from 0. If the bite has already taken it, the nearest whole one breaks. A picture cracks at four tenths of its width.
BITEscript.js1.3How wide the bite is, in letter heights.
DRIPSscript.js5How many drips run from the bite, at most: they only start where there is still logo around the hole.
DINOscript.js2.4How tall the dinosaur 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 bitten and dripping before it heals.
LOOPscript.jstrueWhether the logo heals and the story starts again. With false it stays bitten and keeps dripping.

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 studio’s site or video, a 404 page or a loading screen with a sense of humour, a social post. It works with a written wordmark and with a picture.

On phones

The same story, with the sizes adapted: on a tall screen the dinosaur is a little bigger and, when it stops, only its head and chest are in view. A tap restarts it.

With reduced motion

Nothing moves: the logo fades in, then the dinosaur next to it, then the bite, the blood and the crack fade in, and the dinosaur fades away. If the story starts again, the healing is a fade too.

Pitfalls

  • A mask with maskUnits userSpaceOnUse lives in the coordinates of the element that uses it, transform included: it goes on the letter that moves, otherwise the letter hops and the hole stays still.
  • Two clipped halves placed side by side leave a thin line where they meet (antialiasing): until the letter cracks the whole one is shown.
  • getBBox ignores the clipPath: each half of the letter has the box of the whole letter, so the corners they turn around are chosen on that.
  • The inside of the mouth, turned together with the jaw, stuck out of the snout: it is stretched instead of turned, by the cosine across and the sine down.
  • The wound gradient would colour the letter while it is still whole: it is shown only from the bite, and while healing it disappears before the hole closes.
  • A picture from another site cannot be read on a canvas (getImageData throws): then the drips are spread along the left side of the bite.
  • Pieces of the same green drawn on top of each other disappear (the little arms over the chest showed only their claws): every piece has an outline, and the body’s outline is a separate path that stops where the tail begins, so the joint shows no line.

Libraries

GSAP 3.15.0, Unbounded (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 16 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