Vai al contenuto
animorio
EN
Tutti i componenti

L’avviso del timbro

Notifiche, SVG, HoverGSAP, Solo CSSMediaPeso compresso: Demo 5,4 KBGSAP 28 KBGratisScarica lo zip

Nello stile minimal, su bianco: l’avviso di pagamento di un piccolo negozio di ceramiche. Premendo Pay scende un foglietto di carta con un’oscillazione; un timbro di gomma col manico di legno cala sul suo angolo, la carta cede di un pixel sotto il colpo, e quando il timbro si alza resta PAID nell’inchiostro vermiglio, un po’ storto e con la grana vera dell’inchiostro. Il titolo passa da Processing payment a Payment received; gli avvisi si impilano e se ne vanno dopo qualche secondo.

Il codice

Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN. Nella scheda React la stessa demo è già un componente, che spegne le sue animazioni quando esce dalla pagina.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The rubber stamp notification</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the rubber stamp notification: the payment confirmation of a small shop, on white. Every payment drops a
         paper notice from the top; a rubber stamp comes down on its corner and leaves PAID in vermilion ink. The
         notices stack, the oldest slips away -->
    <div class="stamp-demo" data-demo>
      <div class="stack" data-stack aria-live="polite"></div>

      <button class="pay" type="button" data-pay data-autoclic>
        <span class="pay__label" data-pay-label>Pay €48.00</span>
      </button>
      <p class="note" data-note>Fern &amp; Co · ceramics</p>
    </div>

    <template data-toast>
      <article class="toast" role="status">
        <div class="toast__paper" data-paper>
          <div class="toast__text">
            <p class="toast__shop" data-shop></p>
            <p class="toast__title" data-title></p>
            <p class="toast__meta" data-meta></p>
          </div>
          <svg class="toast__ink" viewBox="0 0 120 120" aria-hidden="true" data-ink>
            <defs>
              <filter id="inchiostro" x="-10%" y="-10%" width="120%" height="120%">
                <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="4" result="grana"/>
                <feColorMatrix in="grana" type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 -1.5 1.42" result="buchi"/>
                <feComposite in="SourceGraphic" in2="buchi" operator="in"/>
              </filter>
            </defs>
            <g filter="url(#inchiostro)" class="toast__ink-g">
              <circle cx="60" cy="60" r="52" class="toast__ring"/>
              <circle cx="60" cy="60" r="45" class="toast__ring toast__ring--thin"/>
              <text x="60" y="69" text-anchor="middle" class="toast__paid" data-word></text>
              <text x="60" y="90" text-anchor="middle" class="toast__date" data-date></text>
              <path d="M22 41 H98 M22 79 H98" class="toast__ring toast__ring--thin"/>
            </g>
          </svg>
          <button class="toast__close" type="button" aria-label="Dismiss notification" data-close>
            <svg viewBox="0 0 12 12" aria-hidden="true"><path d="M2.5 2.5l7 7M9.5 2.5l-7 7"/></svg>
          </button>
        </div>
        <div class="toast__stamp" data-stamp aria-hidden="true">
          <svg viewBox="0 0 80 120">
            <defs>
              <linearGradient id="manico" x1="0" x2="1">
                <stop offset="0" stop-color="#a77b4f"/>
                <stop offset="0.4" stop-color="#d2a877"/>
                <stop offset="1" stop-color="#8f6640"/>
              </linearGradient>
              <linearGradient id="ottone" x1="0" x2="1">
                <stop offset="0" stop-color="#9a8a62"/>
                <stop offset="0.45" stop-color="#e7dcb6"/>
                <stop offset="1" stop-color="#7d6e4a"/>
              </linearGradient>
            </defs>
            <ellipse cx="40" cy="16" rx="17" ry="14" fill="url(#manico)"/>
            <ellipse cx="34" cy="11" rx="5" ry="3" fill="#fff" opacity="0.35"/>
            <path d="M33 28 Q40 32 47 28 L46 66 Q40 69 34 66 Z" fill="url(#manico)"/>
            <rect x="22" y="66" width="36" height="10" rx="1.5" fill="url(#ottone)"/>
            <rect x="14" y="76" width="52" height="30" rx="2" fill="#2a2724"/>
            <rect x="14" y="76" width="52" height="4" fill="#fff" opacity="0.08"/>
            <rect x="16" y="106" width="48" height="5" rx="1" fill="var(--accento)"/>
          </svg>
        </div>
      </article>
    </template>
  </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

Cambia valori, colori e testi con le manopole e guarda l’animazione rispondere dal vivo. Oppure scrivi tu nel codice. Poi scarica la cartella con le tue modifiche.

17 valori da cambiare

Oppure chiedila a Claude Code

Col connettore di Animorio, Claude Code la prende da qui con tutta la sua guida e la adatta al tuo progetto. Incolla questa richiesta:

Prendi «L’avviso del timbro» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco c’è il pulsante nero Pay €48.00 e, sopra, uno spazio vuoto. Premendolo scende dall’alto un avviso di carta color avorio col bordo sottile e un’ombra morbida: in alto Fern & Co in piccolo, poi Processing payment… in grigio e la riga Order 2418 · €48.00. Entra un poco ruotato e si raddrizza con un rimbalzo. Subito dopo un timbro di gomma col pomo e il manico di legno, la ghiera d’ottone e la gomma nera cala sull’angolo destro dell’avviso, rallenta, poi batte: la carta si abbassa e si schiaccia di un pixel o due e torna su con una molla, e quando il timbro si alza e sparisce resta il timbro vermiglio, un doppio cerchio con PAID e la data, un po’ storto e con i buchi della grana dell’inchiostro, ogni volta diversi. Il titolo diventa Payment received in nero. Premendo di nuovo arriva un altro avviso col suo ordine e il suo importo, e quelli di prima scendono di un gradino dietro, più piccoli e più chiari; dopo sei secondi ognuno sale e sparisce, e la crocetta lo chiude prima.

Come funziona

Un avviso da un modello

Ogni avviso nasce da un template: la carta, i tre testi, l’impronta in SVG e il timbro, che sta fuori dalla carta così la carta può abbassarsi sotto di lui. Gli avvisi entrano in cima alla pila con prepend e una sola funzione li rimette in fila: il primo a zero, gli altri 13 pixel più giù per gradino, un po’ più piccoli e più chiari.

Il timbro misurato al momento

Prima del colpo lo script misura dove sta l’impronta con getBoundingClientRect e mette il timbro sopra di lei, largo una volta e sei decimi l’impronta, con la faccia di gomma sul suo centro: così il colpo cade giusto a ogni misura, anche dopo un cambio di finestra.

Il colpo

Una timeline sola: l’avviso scende con back.out(1.7), il timbro arriva in 0,34 secondi e poi batte in 0,14 con power3.in, che accelera come una mano vera. Nello stesso istante la carta si abbassa e si schiaccia di PRESS pixel e torna con elastic.out, e l’impronta compare un pelo più grande e si posa, ruotata a caso fino a TILT gradi.

L’inchiostro

L’impronta passa da un filtro SVG: feTurbulence fa la grana, una matrice di colore la trasforma in buchi e feComposite li toglie dall’inchiostro. Ogni avviso ha il suo filtro, con un id e un seme suoi, così nessun timbro è uguale all’altro.

Accessibile

La pila è aria-live, ogni avviso è role status e la crocetta ha la sua etichetta; il fuoco da tastiera ha l’anello solo con la tastiera. Col movimento ridotto il timbro non c’è: l’avviso e l’impronta compaiono in dissolvenza.

Valori da cambiare

NomeFileDi partenzaCosa cambia
SHOPscript.jsFern & CoIl nome del negozio su ogni avviso.
WORDscript.jsPAIDLa parola che lascia il timbro.
DONEscript.jsPayment receivedIl titolo dopo il colpo.
WAITscript.jsProcessing paymentIl titolo mentre il timbro scende.
DWELLscript.js6Quanti secondi resta un avviso prima di andarsene.
PRESSscript.js2Di quanti pixel cede la carta sotto il timbro.
TILTscript.js7Di quanti gradi al massimo l’impronta può venire storta.
STACKscript.js3Quanti avvisi restano impilati.

Provali nel Playground

Quando usarla

Per la conferma di un pagamento o di un ordine in un negozio, una prenotazione accettata, una fattura pagata, una pratica approvata: dove un timbro dice che la cosa è fatta.

Sul telefono

L’avviso si stringe con lo schermo, l’impronta e il timbro si rimpiccioliscono un poco e il colpo si misura sull’impronta vera, quindi cade giusto; il tocco fa quello che fa il clic.

Con il movimento ridotto

Il timbro non c’è: l’avviso compare in dissolvenza, l’impronta arriva in dissolvenza mezzo secondo dopo e gli avvisi se ne vanno senza spostarsi.

Trappole

  • Con un template gli id dei filtri SVG si ripetono a ogni avviso e il browser usa sempre il primo: ogni copia deve avere un id suo e il riferimento url() aggiornato, sennò tutti i timbri hanno la stessa grana.
  • Il timbro va fuori dall’elemento che si schiaccia: dentro la carta si schiacciava con lei e sembrava di gomma molle.
  • La faccia del timbro deve coprire tutta l’impronta: più stretta, nel colpo si vedeva l’anello rosso sporgere ai lati e il timbro sembrava piccolo.
  • Il colpo si misura al momento con getBoundingClientRect, non una volta all’apertura: la pila sposta gli avvisi e la finestra può cambiare misura.

Librerie

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 5,4 KB; le librerie: GSAP 28 KB.

Collaudo

Provata il 24 ottobre 2026

  • Computer: Fatto
  • Telefono: Fatto
  • Movimento ridotto: Fatto
  • Safari su iPhone: Da fare

Licenza d’uso

Puoi usarla nei tuoi progetti e in quelli dei tuoi clienti. Non puoi rivenderla né ridistribuirla così com’è. GSAP resta sotto la sua licenza Standard. Licenza completa.

Tutti i componenti