Skip to content
animorio
IT
Back to the library

The clock that counts the minutes

Between one chapter and the next a dark card slides in: the name cuts in, then a huge clock counts the minutes up to the chapter's time and the new page arrives from the side.

Transitions, TextGSAPMediumFree

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN.

<!doctype html>
<html lang="it">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>L’orologio che conta i minuti</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- i fotogrammi: scene in bianco e nero disegnate a mano, riquadro 300 x 200 -->
  <svg class="scene" aria-hidden="true" focusable="false" width="0" height="0">
    <defs>
      <linearGradient id="g-notte" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#090909" /><stop offset="1" stop-color="#262626" /></linearGradient>
      <radialGradient id="g-faro"><stop offset="0" stop-color="#ffffff" /><stop offset="0.32" stop-color="#ececec" /><stop offset="1" stop-color="#ececec" stop-opacity="0" /></radialGradient>
      <linearGradient id="g-fascio" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#ffffff" stop-opacity="0.55" /><stop offset="1" stop-color="#ffffff" stop-opacity="0" /></linearGradient>
      <linearGradient id="g-cielo" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#dcdcdc" /><stop offset="1" stop-color="#9c9c9c" /></linearGradient>
      <radialGradient id="g-luce"><stop offset="0" stop-color="#ffffff" /><stop offset="0.5" stop-color="#d9d9d9" /><stop offset="1" stop-color="#d9d9d9" stop-opacity="0" /></radialGradient>
      <pattern id="p-scacchi" width="26" height="26" patternUnits="userSpaceOnUse" patternTransform="skewY(-6)">
        <rect width="26" height="26" fill="#efefef" /><rect width="13" height="13" fill="#121212" /><rect x="13" y="13" width="13" height="13" fill="#121212" />
      </pattern>

      <symbol id="s-fari" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="url(#g-notte)" />
        <rect y="150" width="300" height="50" fill="#121212" />
        <path d="M58 140 Q150 112 242 140 L252 152 L48 152 Z" fill="#040404" />
        <path d="M104 128 L0 200 L150 200 Z" fill="url(#g-fascio)" opacity="0.45" />
        <path d="M196 128 L300 200 L150 200 Z" fill="url(#g-fascio)" opacity="0.45" />
        <circle cx="104" cy="130" r="30" fill="url(#g-faro)" />
        <circle cx="196" cy="130" r="30" fill="url(#g-faro)" />
      </symbol>

      <symbol id="s-gomme" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#bdbdbd" />
        <rect y="160" width="300" height="40" fill="#8f8f8f" />
        <g fill="none">
          <circle cx="104" cy="126" r="40" stroke="#151515" stroke-width="26" />
          <circle cx="104" cy="126" r="53" stroke="#2b2b2b" stroke-width="4" stroke-dasharray="3 5" />
          <circle cx="196" cy="126" r="40" stroke="#151515" stroke-width="26" />
          <circle cx="196" cy="126" r="53" stroke="#2b2b2b" stroke-width="4" stroke-dasharray="3 5" />
          <circle cx="150" cy="44" r="30" stroke="#1d1d1d" stroke-width="20" />
        </g>
        <circle cx="104" cy="126" r="17" fill="#7a7a7a" />
        <circle cx="196" cy="126" r="17" fill="#7a7a7a" />
        <circle cx="150" cy="44" r="12" fill="#8a8a8a" />
      </symbol>

      <symbol id="s-bandiera" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="url(#g-cielo)" />
        <rect x="68" y="26" width="6" height="174" fill="#1a1a1a" />
        <path d="M74 32 C118 16 160 48 204 34 C230 26 250 28 264 32 L264 124 C250 120 230 118 204 126 C160 140 118 108 74 124 Z" fill="url(#p-scacchi)" />
        <path d="M74 32 C118 16 160 48 204 34 C230 26 250 28 264 32 L264 124 C250 120 230 118 204 126 C160 140 118 108 74 124 Z" fill="#000" opacity="0.14" />
      </symbol>

      <symbol id="s-casco" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#2a2a2a" />
        <rect y="152" width="300" height="48" fill="#191919" />
        <path d="M90 152 C86 92 122 54 170 54 C218 54 238 92 238 128 L238 152 Z" fill="#e3e3e3" />
        <path d="M148 96 C170 86 214 86 238 100 L238 130 C212 124 172 124 148 130 Z" fill="#0f0f0f" />
        <path d="M100 120 C118 72 170 62 214 72" fill="none" stroke="#8c8c8c" stroke-width="10" />
      </symbol>

      <symbol id="s-rettilineo" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#cdcdcd" />
        <rect y="90" width="300" height="110" fill="#5a5a5a" />
        <path d="M141 90 L159 90 L300 200 L0 200 Z" fill="#222" />
        <path d="M141 90 L0 200" stroke="#f1f1f1" stroke-width="7" stroke-dasharray="9 9" />
        <path d="M159 90 L300 200" stroke="#f1f1f1" stroke-width="7" stroke-dasharray="9 9" />
        <g fill="#e9e9e9">
          <path d="M149.2 98 L150.8 98 L151.3 106 L148.7 106 Z" />
          <path d="M148.2 116 L151.8 116 L152.8 130 L147.2 130 Z" />
          <path d="M146.6 144 L153.4 144 L155.4 166 L144.6 166 Z" />
          <path d="M144 182 L156 182 L158.4 200 L141.6 200 Z" />
        </g>
      </symbol>

      <symbol id="s-semaforo" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#141414" />
        <rect x="146" y="0" width="8" height="70" fill="#222" />
        <rect x="38" y="68" width="224" height="60" rx="8" fill="#2a2a2a" />
        <circle cx="70" cy="98" r="30" fill="url(#g-luce)" />
        <circle cx="110" cy="98" r="30" fill="url(#g-luce)" />
        <circle cx="70" cy="98" r="14" fill="#fafafa" />
        <circle cx="110" cy="98" r="14" fill="#fafafa" />
        <circle cx="150" cy="98" r="14" fill="#3b3b3b" />
        <circle cx="190" cy="98" r="14" fill="#3b3b3b" />
        <circle cx="230" cy="98" r="14" fill="#3b3b3b" />
      </symbol>

      <symbol id="s-volante" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#d4d4d4" />
        <circle cx="150" cy="104" r="68" fill="none" stroke="#141414" stroke-width="18" />
        <path d="M150 104 L86 90 M150 104 L214 90 M150 104 L150 170" stroke="#141414" stroke-width="12" stroke-linecap="round" />
        <circle cx="150" cy="104" r="22" fill="#2b2b2b" />
      </symbol>

      <symbol id="s-box" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#999" />
        <rect x="40" y="34" width="220" height="166" fill="#0e0e0e" />
        <rect x="40" y="34" width="220" height="72" fill="#bcbcbc" />
        <g stroke="#7b7b7b" stroke-width="3">
          <path d="M40 44 H260 M40 54 H260 M40 64 H260 M40 74 H260 M40 84 H260 M40 94 H260" />
        </g>
        <rect x="118" y="146" width="64" height="34" fill="#3a3a3a" />
        <circle cx="128" cy="186" r="7" fill="#5a5a5a" />
        <circle cx="172" cy="186" r="7" fill="#5a5a5a" />
      </symbol>

      <symbol id="s-tribuna" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#ececec" />
        <path d="M0 36 L300 16 L300 28 L0 50 Z" fill="#1c1c1c" />
        <path d="M0 70 L300 54 L300 64 L0 82 Z" fill="#8a8a8a" />
        <path d="M0 96 L300 78 L300 90 L0 110 Z" fill="#747474" />
        <path d="M0 124 L300 104 L300 118 L0 140 Z" fill="#5e5e5e" />
        <path d="M0 154 L300 132 L300 148 L0 172 Z" fill="#484848" />
        <rect y="178" width="300" height="22" fill="#2e2e2e" />
      </symbol>

      <symbol id="s-pioggia" viewBox="0 0 300 200">
        <rect width="300" height="200" fill="#4a4a4a" />
        <g stroke="#cfcfcf" stroke-width="1.6" stroke-linecap="round" opacity="0.7">
          <path d="M20 10 l8 22 M60 30 l8 22 M100 6 l8 22 M140 40 l8 22 M180 12 l8 22 M220 34 l8 22 M260 8 l8 22 M40 70 l8 22 M80 94 l8 22 M120 66 l8 22 M160 100 l8 22 M200 72 l8 22 M240 96 l8 22 M280 60 l8 22 M30 130 l8 22 M70 150 l8 22 M110 124 l8 22 M150 150 l8 22 M190 128 l8 22 M230 150 l8 22 M270 120 l8 22" />
        </g>
        <path d="M0 200 C80 146 220 146 300 200 Z" fill="#232323" />
        <path d="M150 196 L70 150" stroke="#0f0f0f" stroke-width="6" stroke-linecap="round" />
      </symbol>
    </defs>
  </svg>

  <!-- i capitoli: uno alla volta; fra l'uno e l'altro passa la scheda con l'orologio -->
  <main class="pagine">
    <section class="pagina pagina--giallo attiva" data-titolo="Partenza" data-giorno="Primo giorno" data-da="06:15" data-a="06:30" data-sotto="Il furgone lascia l’officina prima che faccia chiaro" aria-label="Partenza">
      <div class="pagina__testo">
        <p class="pagina__quando">Primo giorno, 06:30</p>
        <h2 class="pagina__titolo">Partenza</h2>
        <p class="pagina__corpo">Il furgone esce quando è ancora buio. Dietro, le gomme legate con le cinghie e un thermos che nessuno ha chiuso bene.</p>
      </div>
      <figure class="pagina__foto" aria-hidden="true"><div class="pagina__foto-dentro"><svg viewBox="0 0 300 200" preserveAspectRatio="xMidYMid slice"><use href="#s-gomme" /></svg></div></figure>
    </section>
    <section class="pagina pagina--carta" data-titolo="Il box" data-giorno="Primo giorno" data-da="06:30" data-a="09:15" data-sotto="Le serrande si alzano una dopo l’altra" aria-label="Il box">
      <div class="pagina__testo">
        <p class="pagina__quando">Primo giorno, 09:15</p>
        <h2 class="pagina__titolo">Il box</h2>
        <p class="pagina__corpo">Ogni box ha già il suo rumore: un compressore, una radio accesa, una chiave che cade sul cemento.</p>
      </div>
      <figure class="pagina__foto" aria-hidden="true"><div class="pagina__foto-dentro"><svg viewBox="0 0 300 200" preserveAspectRatio="xMidYMid slice"><use href="#s-box" /></svg></div></figure>
    </section>
    <section class="pagina pagina--inchiostro" data-titolo="La notte" data-giorno="Primo giorno" data-da="21:40" data-a="22:30" data-sotto="I fari passano più veloci del rumore" aria-label="La notte">
      <div class="pagina__testo">
        <p class="pagina__quando">Primo giorno, 22:30</p>
        <h2 class="pagina__titolo">La notte</h2>
        <p class="pagina__corpo">Dopo il tramonto la pista diventa una fila di fari. Il rumore arriva sempre un attimo dopo la luce.</p>
      </div>
      <figure class="pagina__foto" aria-hidden="true"><div class="pagina__foto-dentro"><svg viewBox="0 0 300 200" preserveAspectRatio="xMidYMid slice"><use href="#s-fari" /></svg></div></figure>
    </section>
    <section class="pagina pagina--carta" data-titolo="L’alba" data-giorno="Secondo giorno" data-da="05:20" data-a="06:05" data-sotto="La pioggia smette quando nessuno guarda" aria-label="L’alba">
      <div class="pagina__testo">
        <p class="pagina__quando">Secondo giorno, 06:05</p>
        <h2 class="pagina__titolo">L’alba</h2>
        <p class="pagina__corpo">Ha piovuto tutta la notte. Il primo a vedere il cielo che si apre è chi asciuga i cordoli.</p>
      </div>
      <figure class="pagina__foto" aria-hidden="true"><div class="pagina__foto-dentro"><svg viewBox="0 0 300 200" preserveAspectRatio="xMidYMid slice"><use href="#s-pioggia" /></svg></div></figure>
    </section>
    <section class="pagina pagina--giallo" data-titolo="L’arrivo" data-giorno="Secondo giorno" data-da="15:10" data-a="15:30" data-sotto="La bandiera scende una volta sola" aria-label="L’arrivo">
      <div class="pagina__testo">
        <p class="pagina__quando">Secondo giorno, 15:30</p>
        <h2 class="pagina__titolo">L’arrivo</h2>
        <p class="pagina__corpo">Ventiquattro ore per venti secondi di bandiera. Poi tutti corrono in pista e i box restano vuoti.</p>
      </div>
      <figure class="pagina__foto" aria-hidden="true"><div class="pagina__foto-dentro"><svg viewBox="0 0 300 200" preserveAspectRatio="xMidYMid slice"><use href="#s-bandiera" /></svg></div></figure>
    </section>
  </main>

  <!-- la scheda scura: prima il nome del capitolo, poi l'orologio che conta fino all'ora giusta -->
  <div class="scheda" aria-hidden="true">
    <p class="scheda__titolo"><span class="scheda__parola">Partenza</span></p>
    <div class="scheda__orologio">
      <p class="scheda__giorno"><span>Primo giorno</span></p>
      <p class="scheda__ora"><span class="cifra">0</span><span class="cifra">6</span><span class="due-punti">:</span><span class="cifra">1</span><span class="cifra">5</span></p>
      <p class="scheda__sotto"></p>
    </div>
  </div>

  <button type="button" class="avanti">Capitolo dopo</button>
  <p class="annuncio" aria-live="polite"></p>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

What it does

Every chapter has a time. To move to the next one a black card slides in from the right and turns ink grey; on it, cut in at once, the chapter's name as wide as the screen. After a second and a half the name disappears and in its place a huge clock counts the minutes from the previous time to the chapter's, with a blinking colon and digits that jump slightly at every minute. Below, the day and a sentence rising word by word. When the count ends the new page arrives from the side and covers the card; its photo lags a moment behind inside the frame.

How it works

The card

A fixed card enters with xPercent from 100 to 0 in 0.8 seconds with expo.out (from the bottom on phones) while its background goes from black to ink grey. Name and clock are not animated: they appear and disappear with a visibility set, hard cuts as in film editing.

The count

The clock counts in total minutes (hours times 60 plus minutes), so it crosses hours and even midnight. An object goes from the starting minutes to the arrival ones with power2.inOut; in onUpdate the value is floored and the time is rewritten only when the minute changes, with a small jump of the digits instead of a tick.

Steady digits

Each digit sits in a fixed-width box (0.5em, centred text): without it, the clock shakes while it counts. Tabular figures (tabular-nums) would do the same, but in Mona Sans they have a slashed zero. The colon blinks in CSS with a step-end animation on visibility.

The page that arrives

Each page is a fixed layer of its own, so the new one can pass over the card with a higher z-index. It enters with x from the screen width to 0; the photo inside the frame is 14% wider and starts offset, so it arrives a little after the page.

Values to change

NameFileDefaultWhat it changes
ENTRATAscript.js0.8Seconds for the card to slide in.
TITOLOscript.js1.5How many seconds the chapter name stays before the clock.
CONTAscript.js1Seconds of the count, whatever the distance between the two times.
ATTESAscript.js2.6Seconds on each page before the next chapter. With 0 it only changes with the button.
data-da, data-aindex.html06:15, 06:30On each page: the time the count starts from and the chapter's time.

When to use it

For a story split into moments: the schedule of a day, the stages of a trip, the hours of an event. The transition takes four seconds: fine between chapters, not between any two pages of a site.

On phones

The card rises from the bottom instead of entering from the side, the photo goes above the text and the clock adapts to the width.

With reduced motion

No card and no count: the button goes straight to the next chapter, which already shows its time. Chapters do not change on their own.

Pitfalls

  • With proportional figures every digit has its own width and the clock wobbles while it counts: you need fixed boxes or tabular figures.
  • Count in total minutes, not in separate hours and minutes: otherwise from 06:30 to 09:15 the minutes run backwards.
  • If all the pages sit inside a fixed container, that container creates a stacking context and the new page never passes over the card: every page must be fixed on its own.
  • The original site makes the clock tick with a sound: if you add it, start it only after a click and always leave a way to turn it off.

Libraries

GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.

Weight: 23 KB of our own files.

Testing

Tested on 27 September 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: Done

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