Vai al contenuto
animorio
EN
Torna alla libreria

La macchina nel calendario

Scroll, SVGGSAP, Solo CSSFacilePeso compresso: Demo 5,4 KBGSAP + ScrollTrigger 45 KBGratisScarica lo zip

Scorri dentro l’anteprima

Il calendario di una stagione, una gara per riga. Quando la lista arriva a metà schermo una macchina vista dall’alto entra e resta lì mentre le righe le scorrono sotto, e la riga che le passa sotto si accende. Alla fine se ne va, e se torni su rientra dal basso, girata.

Il codice

Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN. Nelle schede React e Vue 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 car in the calendar</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/big-shoulders-display@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/barlow@5.3.0/400.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/barlow@5.3.0/600.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="bar">
    <a class="brand" href="#">Brightwater Racing</a>
    <nav class="bar__nav" aria-label="Sections">
      <a href="#">Team</a>
      <a href="#">Calendar</a>
      <a href="#">Tickets</a>
    </nav>
  </header>

  <section class="intro">
    <p class="intro__kicker">Car 11 · Coastal GT Cup</p>
    <h1 class="intro__title">Nine weekends, one car, the whole coast.</h1>
    <p class="intro__hint">Scroll down the calendar, then back up.</p>
  </section>

  <!-- the calendar: the car waits above the screen, drives in when the list reaches the middle and leaves at its end -->
  <section class="calendar" data-calendar>
    <div class="calendar__sticky" aria-hidden="true">
      <div class="drift" data-drift>
        <svg class="car" data-car viewBox="0 0 200 420">
          <defs>
            <radialGradient id="shadow" cx="0.5" cy="0.5" r="0.5">
              <stop offset="0.55" stop-color="#000" stop-opacity="0.55"/>
              <stop offset="1" stop-color="#000" stop-opacity="0"/>
            </radialGradient>
            <linearGradient id="paint" x1="0" y1="0" x2="1" y2="0">
              <stop offset="0" stop-color="#d9dde4"/>
              <stop offset="0.18" stop-color="#ffffff"/>
              <stop offset="0.82" stop-color="#ffffff"/>
              <stop offset="1" stop-color="#d9dde4"/>
            </linearGradient>
            <linearGradient id="glass" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" stop-color="#2a3140"/>
              <stop offset="1" stop-color="#0e1118"/>
            </linearGradient>
            <clipPath id="body"><path d="M36 28C60 16 140 16 164 28C176 34 182 48 184 66L188 118C190 140 186 160 184 176L182 246C184 268 190 290 188 316L184 366C182 392 166 410 136 414C112 417 88 417 64 414C34 410 18 392 16 366L12 316C10 290 16 268 18 246L16 176C14 160 10 140 12 118L16 66C18 48 24 34 36 28Z"/></clipPath>
          </defs>
          <ellipse cx="100" cy="216" rx="112" ry="222" fill="url(#shadow)"/>
          <!-- the tyres, peeking out under the arches -->
          <g fill="#151820">
            <rect x="2" y="64" width="26" height="70" rx="7"/><rect x="172" y="64" width="26" height="70" rx="7"/>
            <rect x="2" y="290" width="26" height="70" rx="7"/><rect x="172" y="290" width="26" height="70" rx="7"/>
          </g>
          <!-- the body and its livery -->
          <path d="M36 28C60 16 140 16 164 28C176 34 182 48 184 66L188 118C190 140 186 160 184 176L182 246C184 268 190 290 188 316L184 366C182 392 166 410 136 414C112 417 88 417 64 414C34 410 18 392 16 366L12 316C10 290 16 268 18 246L16 176C14 160 10 140 12 118L16 66C18 48 24 34 36 28Z" fill="url(#paint)"/>
          <g clip-path="url(#body)">
            <rect x="70" y="0" width="22" height="420" fill="#b6ff3b"/>
            <rect x="108" y="0" width="22" height="420" fill="#b6ff3b"/>
            <rect x="94" y="0" width="12" height="420" fill="#0b0e14"/>
            <path d="M0 196H200V214H0Z" fill="#0b0e14" opacity="0.08"/>
          </g>
          <!-- the rear window, the roof with its number, the windscreen -->
          <path d="M50 106C70 98 130 98 150 106L146 146C120 140 80 140 54 146Z" fill="url(#glass)"/>
          <circle cx="100" cy="192" r="30" fill="#ffffff" stroke="#0b0e14" stroke-width="5"/>
          <text x="100" y="206" text-anchor="middle" font-family="'Big Shoulders Display Variable', Impact, sans-serif" font-weight="900" font-size="38" fill="#0b0e14">11</text>
          <path d="M46 262C72 248 128 248 154 262L162 304C126 294 74 294 38 304Z" fill="url(#glass)"/>
          <path d="M60 266C80 258 104 256 122 258" fill="none" stroke="#fff" stroke-opacity="0.35" stroke-width="4" stroke-linecap="round"/>
          <!-- mirrors, headlights, the rear wing -->
          <path d="M18 252L4 246L4 262L18 266Z" fill="#0b0e14"/><path d="M182 252L196 246L196 262L182 266Z" fill="#0b0e14"/>
          <path d="M34 384C42 396 54 404 68 406L64 394C52 392 42 388 34 384Z" fill="#fff6c9"/>
          <path d="M166 384C158 396 146 404 132 406L136 394C148 392 158 388 166 384Z" fill="#fff6c9"/>
          <rect x="0" y="4" width="200" height="22" rx="4" fill="#0b0e14"/>
          <rect x="0" y="2" width="10" height="30" rx="3" fill="#0b0e14"/><rect x="190" y="2" width="10" height="30" rx="3" fill="#0b0e14"/>
        </svg>
      </div>
    </div>

    <h2 class="calendar__title">Calendar 2027</h2>
    <ol class="rounds" data-rounds>
      <li class="round" data-round><span class="round__no">Round 1</span><b class="round__name">Harbour Ring</b><span class="round__date">14–16.03.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 2</span><b class="round__name">Saltmarsh Park</b><span class="round__date">04–06.04.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 3</span><b class="round__name">Ridgeback Circuit</b><span class="round__date">25–27.04.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 4</span><b class="round__name">Lantern Bay Streets</b><span class="round__date">16–18.05.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 5</span><b class="round__name">Pine Hollow Raceway</b><span class="round__date">06–08.06.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 6</span><b class="round__name">Kestrel Downs</b><span class="round__date">27–29.06.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 7</span><b class="round__name">Copperfield Speedway</b><span class="round__date">18–20.07.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Round 8</span><b class="round__name">Blue Mesa International</b><span class="round__date">22–24.08.2027</span><i class="round__line" data-line></i></li>
      <li class="round" data-round><span class="round__no">Finale</span><b class="round__name">Winter Hill</b><span class="round__date">03–05.10.2027</span><i class="round__line" data-line></i></li>
    </ol>
  </section>

  <section class="outro">
    <h2 class="outro__title">See you at the first corner.</h2>
    <a class="outro__link" href="#">Get weekend passes</a>
  </section>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.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.

48 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 «La macchina nel calendario» da Animorio e adattala al mio sito

Cosa fa

La pagina di una squadra corse inventata, Brightwater Racing, con il calendario della stagione 2027: nove fine settimana su circuiti inventati, uno per riga, col numero del giro, il nome del circuito e le date, separati da una riga sottile. Quando l’inizio del calendario arriva a metà schermo, da sopra entra una macchina vista dall’alto, bianca con due strisce verde lime e il numero 11 sul tetto, e si ferma al centro dello schermo, sopra la lista. Le righe le scorrono sotto: quella che attraversa la metà dello schermo diventa verde lime, testo e riga, e torna bianca quando la lascia. Mentre il calendario passa la macchina deriva piano. Quando la fine della lista passa la metà, la macchina se ne va verso il basso; se torni su, rientra dal basso col muso in su, e uscendo in alto si rigira.

Come funziona

La cornice che si ferma

Il primo figlio della sezione è una cornice sticky alta uno schermo, con un margine sotto negativo della stessa altezza, così non spinge giù la lista. La macchina sta al centro della cornice. La sezione ha overflow: clip, che taglia la macchina ai bordi della sezione senza rompere lo sticky.

La macchina

Due ScrollTrigger con callback: quando la cima della sezione passa la linea a LINE% dello schermo la macchina entra (y a 0, IN secondi, expo.out); quando la fine della lista passa la stessa linea esce verso il basso (y a uno schermo, OUT secondi, expo.in) e solo a fine uscita gira di 180 gradi. Tornando su succede il contrario: rientra dal basso col muso in su, ed esce in alto rigirandosi a 0 gradi.

Le righe

Ogni riga ha il suo ScrollTrigger, da quando la sua cima passa la linea a quando ci passa il suo fondo. Entrando, testo e riga prendono il colore d’accento in ON secondi con power2.out; uscendo tornano al loro colore in OFF secondi con power2.inOut.

La deriva e il ritorno

Un tween legato allo scorrimento sposta la cornice da -DRIFT% a DRIFT% mentre la sezione attraversa lo schermo. A ogni refresh una funzione guarda dove sono la sezione e la fine della lista e mette la macchina subito dove deve stare, sopra, dentro o sotto, girata giusta.

Valori da cambiare

NomeFileDi partenzaCosa cambia
INscript.js0.8I secondi in cui la macchina entra.
OUTscript.js0.8I secondi in cui se ne va.
DRIFTscript.js12Quanto deriva la macchina mentre passa la lista, come parte della sua cornice (%).
ONscript.js0.2I secondi in cui una riga si accende.
OFFscript.js0.6I secondi in cui una riga torna com’era.
LINEscript.js50Dove si accendono le righe e dove entra ed esce la macchina, dall’alto dello schermo (%).

Provali nel Playground

Quando usarla

Per un calendario, un programma, una scaletta, le tappe di un viaggio: ogni lista in cui qualcosa avanza. Al posto della macchina può andarci qualunque cosa vista dall’alto, una barca, una bici, un treno.

Sul telefono

La macchina è larga un terzo dello schermo e le righe vanno su due livelli: il giro sopra, nome e date sotto. Il dito scorre come la rotella e la macchina entra ed esce allo stesso modo.

Con il movimento ridotto

La macchina non guida: sparisce in dissolvenza e ricompare dove deve stare, e la cornice non deriva. Le righe si accendono lo stesso.

Trappole

  • Con overflow: hidden la sezione diventa un contenitore che scorre e la cornice sticky smette di fermarsi: serve overflow: clip, che taglia senza creare uno scorrimento.
  • La cornice alta uno schermo va tolta dal flusso con un margine negativo uguale alla sua altezza, altrimenti spinge la lista in basso di uno schermo.
  • Il mezzo giro si dà a macchina uscita, alla fine del tween: girarla mentre è in vista la farebbe sterzare sul posto.
  • Dopo un refresh, o aprendo la pagina a metà, le callback non sono ancora scattate: la macchina va messa subito dove deve stare guardando le posizioni, senza aspettare uno scorrimento.

Librerie

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

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

Collaudo

Provata il 2 ottobre 2026

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

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.

Tutte le animazioni