
The dinosaur-bitten logo
Intro, SVG, Text
NewFree
A logo intro with a wooden rubber stamp: it dips into the ink pad, winds up and prints with a blow that bends the sheet and splashes ink; the logo stays printed with a real ink texture, which dries. 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 rubber-stamp logo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/familjen-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="scena">
<!-- the stage: the script measures it, builds the sheet, the ink pad and the stamp's block, and prints the logo -->
<svg class="palco" data-stage role="img" aria-label="Pressly" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- the grain of the paper: a little tile of specks and fibres the script paints on a canvas -->
<pattern id="grain" patternUnits="userSpaceOnUse" width="180" height="180">
<image width="180" height="180" data-grain-image />
</pattern>
<!-- the ink texture: blotches of more and less ink, and a few pin holes where the rubber did not touch -->
<filter id="ink-noise" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" data-noise>
<feTurbulence type="fractalNoise" numOctaves="3" result="blot" data-noise-blot />
<feColorMatrix in="blot" type="matrix" result="soft" data-noise-soft />
<feTurbulence type="fractalNoise" numOctaves="2" result="dust" data-noise-dust />
<feColorMatrix in="dust" type="matrix" result="holes" data-noise-holes />
<feComposite in="soft" in2="holes" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" />
</filter>
<mask id="ink-mask" maskUnits="userSpaceOnUse" data-ink-mask>
<rect fill="#fff" filter="url(#ink-noise)" data-ink-mask-rect />
</mask>
<!-- the rough edges of a rubber print: the shapes pushed about by a fine noise, a bleed when there is a lot of ink -->
<filter id="ink-rough" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB" data-rough>
<feMorphology operator="dilate" radius="0" result="fat" data-rough-fat />
<feTurbulence type="fractalNoise" numOctaves="2" result="wobble" data-rough-turb />
<feDisplacementMap in="fat" in2="wobble" xChannelSelector="R" yChannelSelector="G" data-rough-disp />
</filter>
<!-- the fresh-ink shine shows only on the print -->
<mask id="print-alpha" maskUnits="userSpaceOnUse" style="mask-type: alpha" data-print-alpha>
<use href="#print-dry" />
</mask>
<linearGradient id="gloss-grad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" class="lucido-stop lucido-stop--via" />
<stop offset="0.5" class="lucido-stop" />
<stop offset="1" class="lucido-stop lucido-stop--via" />
</linearGradient>
<!-- soft shadows -->
<filter id="soft" x="-30%" y="-80%" width="160%" height="260%" data-soft>
<feGaussianBlur stdDeviation="6" data-soft-blur />
</filter>
<!-- the turned handle, to keep its shade, grain and grooves inside it -->
<clipPath id="handle-clip">
<path d="M-54 0L54 0L54 -10C54 -13 51 -14 46 -15C34 -17 26 -24 24 -34C21 -50 18 -66 19 -84C24 -86 28 -88 28 -91L28 -98C28 -101 24 -103 22 -106C36 -112 48 -126 48 -146C48 -170 26 -188 0 -188C-26 -188 -48 -170 -48 -146C-48 -126 -36 -112 -22 -106C-24 -103 -28 -101 -28 -98L-28 -91C-28 -88 -24 -86 -19 -84C-18 -66 -21 -50 -24 -34C-26 -24 -34 -17 -46 -15C-51 -14 -54 -13 -54 -10Z" />
</clipPath>
</defs>
<g data-world>
<!-- the sheet of paper, with the print on it -->
<g data-paper-place>
<g data-paper>
<path class="foglio-ombra foglio-ombra--larga" data-paper-shadow-2 />
<path class="foglio-ombra" data-paper-shadow />
<path class="foglio" data-sheet />
<path class="foglio-grana" fill="url(#grain)" data-sheet-grain />
<path class="foglio-bordo" data-sheet-edge />
<g data-rings></g>
<g filter="url(#ink-rough)" mask="url(#ink-mask)" data-print-holder>
<g id="print-dry" class="stampa" data-print-dry></g>
<g class="stampa-bagnata" data-print-wet></g>
<g class="stampa" data-specks></g>
</g>
<g mask="url(#print-alpha)"><path fill="url(#gloss-grad)" data-gloss /></g>
</g>
</g>
<!-- the ink pad: a tin with its lid open and the felt soaked in ink -->
<g data-pad-place>
<g data-pad></g>
</g>
<!-- the stamp and its shadow; the point in the middle of the rubber's bottom edge is 0 0 -->
<g data-stamp-all>
<rect class="timbro-ombra" filter="url(#soft)" data-stamp-shadow />
<g data-stamp-place>
<!-- the face of the rubber, with the logo the wrong way round: seen only when the stamp tips it towards us -->
<g data-face></g>
<g data-rubber></g>
<g data-upper>
<g data-block></g>
<!-- the turned wooden handle: drawn once, standing on the top of the block -->
<g data-handle-place>
<g data-handle>
<ellipse class="appoggio" cx="0" cy="1" rx="62" ry="9" />
<path class="manico" d="M-54 0L54 0L54 -10C54 -13 51 -14 46 -15C34 -17 26 -24 24 -34C21 -50 18 -66 19 -84C24 -86 28 -88 28 -91L28 -98C28 -101 24 -103 22 -106C36 -112 48 -126 48 -146C48 -170 26 -188 0 -188C-26 -188 -48 -170 -48 -146C-48 -126 -36 -112 -22 -106C-24 -103 -28 -101 -28 -98L-28 -91C-28 -88 -24 -86 -19 -84C-18 -66 -21 -50 -24 -34C-26 -24 -34 -17 -46 -15C-51 -14 -54 -13 -54 -10Z" />
<g clip-path="url(#handle-clip)">
<path class="manico-ombra" d="M24 6C36 -18 28 -52 15 -84C30 -100 42 -122 32 -152C27 -168 20 -180 8 -194L80 -194L80 6Z" />
<path class="manico-vena" d="M-6 -118C-13 -138 -11 -160 2 -180M10 -120C8 -140 14 -160 22 -176M-28 -136C-34 -152 -30 -166 -20 -178M-6 -40C-8 -56 -7 -70 -5 -82M6 -38C4 -54 6 -68 8 -80" />
<path class="manico-riga" d="M-56 -10Q0 -3 56 -10M-30 -91Q0 -86 30 -91M-30 -98Q0 -93 30 -98M-23 -106Q0 -102 23 -106" />
<path class="manico-lucido" d="M-36 -146C-36 -162 -27 -174 -13 -179M-15 -42C-14 -56 -13 -68 -13 -80M-46 -5L-26 -5M-22 -94L-12 -94" />
<ellipse class="manico-riflesso" cx="-22" cy="-160" rx="7" ry="11" transform="rotate(28 -22 -160)" />
</g>
<path class="manico-bordo" d="M-54 0L54 0L54 -10C54 -13 51 -14 46 -15C34 -17 26 -24 24 -34C21 -50 18 -66 19 -84C24 -86 28 -88 28 -91L28 -98C28 -101 24 -103 22 -106C36 -112 48 -126 48 -146C48 -170 26 -188 0 -188C-26 -188 -48 -170 -48 -146C-48 -126 -36 -112 -22 -106C-24 -103 -28 -101 -28 -98L-28 -91C-28 -88 -24 -86 -19 -84C-18 -66 -21 -50 -24 -34C-26 -24 -34 -17 -46 -15C-51 -14 -54 -13 -54 -10Z" />
</g>
</g>
<!-- its face on the front of the block: cheeks, eyes with lids, brows, a mouth -->
<g data-eyes-place>
<g data-eyes>
<ellipse class="guancia" cx="-52" cy="17" rx="10" ry="6" data-cheek />
<ellipse class="guancia" cx="52" cy="17" rx="10" ry="6" data-cheek />
<ellipse class="occhio" cx="-26" cy="0" rx="14" ry="16" />
<ellipse class="occhio" cx="26" cy="0" rx="14" ry="16" />
<g data-pupils>
<circle class="iride" cx="-26" cy="2" r="9" />
<circle class="pupilla" cx="-26" cy="2" r="5" />
<circle class="riflesso" cx="-29.5" cy="-1.6" r="2.6" />
<circle class="iride" cx="26" cy="2" r="9" />
<circle class="pupilla" cx="26" cy="2" r="5" />
<circle class="riflesso" cx="22.5" cy="-1.6" r="2.6" />
</g>
<g data-lids>
<ellipse class="palpebra" cx="-26" cy="0" rx="15.4" ry="17.4" />
<ellipse class="palpebra" cx="26" cy="0" rx="15.4" ry="17.4" />
</g>
<path class="ciglio" d="M-41 -25Q-27 -32 -12 -26" data-brow-l />
<path class="ciglio" d="M12 -26Q27 -32 41 -25" data-brow-r />
<path class="bocca" d="M-10 22Q0 31 10 22" data-smile />
<ellipse class="bocca-aperta" cx="0" cy="26" rx="5.5" ry="6.5" data-oh />
</g>
</g>
</g>
</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>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.
39 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 rubber-stamp 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 everything is counted in letter heights: the rubber is as wide as the logo plus a margin, the block as tall as the logo plus half a letter (so that, squashed, it still covers it), the sheet a little wider, the pad under the sheet. The size is chosen so that the stamp hovering over the print and the pad below both fit; on a tall screen the sheet turns upright.
The print is a group with a filter and a mask. The filter pushes its edges about with a feDisplacementMap driven by a fine feTurbulence (and, with a lot of ink, fattens them with feMorphology). The mask is a white rectangle with a noise filter: a broad feTurbulence, brought between grey and white with feColorMatrix, gives the heavier and lighter patches; a dense, thresholded one gives the pin holes where the rubber did not touch; feComposite arithmetic multiplies them. Every sheet gets new seeds, so every print is different. On top sits a darker copy, the wet ink, which slowly fades: that is the drying.
The turned handle is drawn once in the page, with its shade, grain, rings and highlights clipped inside its outline; the block, the rubber and the pad are built by the script, because they depend on the length of the logo. Place, height above the surface, lean, squash and how far the stamp is tipped towards us live in one object, written as a transform attribute: the origin is the middle of the rubber's edge, so the squash starts there. When it tips, the upper part gets shorter and the face of the rubber appears below it, a trapezoid with the logo mirrored by scale(-1 1). The handle sways with skewX around its base, so it never comes off the block.
The stamp falls with power4.in, squashes for five hundredths of a second and springs back with elastic.out. At the same instant the print appears (hidden under the block), the sheet squashes, its outline (a path of four quadratic curves) bends and quivers through a series of dying curves, two rounded rectangles spread out as a shock wave and the splashes fly outwards from the edges of the rubber, stopped inside the sheet. The suction is the opposite: the stamp stretches while it stays stuck, the sheet bends upwards, then everything lets go with power3.out.
The whole intro is one timeline, with the labels start, arrive, ink, load, press, lift, reveal, bow, fly, rest and timeScale for the speed. At rest the sheet breathes and a glint passes over the print, shown only on the letters by an alpha mask holding a use of the print. If IMAGE holds an address, the logo becomes that picture: a filter turns the dark and coloured parts into ink and leaves the light parts and the transparent background as paper, and the same filter, in rubber colour, cuts it into the stamp's face. 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 | 'Pressly' | The logo as a word: it is cut the wrong way round in the rubber and printed on the sheet. |
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. |
INK | script.js | 1 | How much ink: 0.4 gives a dry, patchy print, 1.5 a full one that bleeds a little. |
PRESS | script.js | 1 | How hard the blow is: how much the stamp squashes and the scene shakes, the sheet bends and the shock wave runs. |
SPLATTER | script.js | 1 | How many ink splashes come out at the edges and how far they go (0 = a clean print). |
TINT | script.js | true | A picture is printed in the ink colour; with false it keeps its own colours, with the ink texture. |
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 printed logo stays on show before the sheet slides away. |
LOOP | script.js | true | Whether the sheet slides away and a new one is printed. With false the logo stays, the sheet breathing and glinting. |
To present a logo with a gesture that smells of paper and offices: the opening of a print shop's site, a design studio, a stationery shop or a craft brand, 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: on a tall screen the sheet stands upright, like a letter, and the logo is almost as wide as the screen. A tap restarts it.
Nothing moves: the sheet and the pad fade in, then the stamp on the pad; stamp and pad fade away and the printed logo fades in in their place. If the animation starts again, the sheet leaves with a fade too.
GSAP 3.15.0, Familjen Grotesk (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 17 KB; the libraries: GSAP 28 KB.
Tested on 10 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.