Vai al contenuto
animorio
EN
Tutti i componenti

Il menu a cassetti

Menu, 3D, FisicaSolo CSS, GSAPImpegnativaPeso compresso: Demo 9,6 KBGSAP 28 KBGratisScarica lo zip

Il menu di un sito come uno schedario d'acciaio in 3D: le voci sono cassetti che escono su una molla al passaggio; quello scelto corre fuori fino al fermo e le cartelline delle sottovoci si alzano una dopo l'altra, con le linguette a scalinata. Cambiando cassetto, quello aperto si chiude di colpo e lo schedario sobbalza.

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 filing drawer menu</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/familjen-grotesk@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/700.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the menu as a filing cabinet: each item is a drawer in 3D. Under the pointer a drawer comes out a little on a
         spring; pressed, it runs out on its rails and its folders rise one after the other, their tabs in a staircase.
         The cabinet's shell, the dark holes and the inside of the drawers are drawn by the script -->
    <nav class="cab" aria-label="Archive" data-cab>
      <div class="cab__scene" data-scene>
        <div class="cab__body" data-body>
          <ul class="cab__drawers">
            <li class="drawer" style="--tint: #e0603f" data-drawer>
              <button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-projects" data-front data-autoclic>
                <span class="drawer__card"><span class="drawer__name">Projects</span><span class="drawer__range">A&ndash;F</span></span>
                <span class="drawer__pull" aria-hidden="true"></span>
              </button>
              <ul class="drawer__folders" id="drawer-projects" aria-label="Projects" data-folders>
                <li><a class="folder" href="#" data-folder aria-current="page"><span class="folder__tab">Residential</span><span class="folder__note">32 houses, 1998&ndash;2026</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Workplace</span><span class="folder__note">Offices and studios</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Hospitality</span><span class="folder__note">Hotels, two harbour baths</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Unbuilt</span><span class="folder__note">Competitions we lost</span></a></li>
              </ul>
            </li>
            <li class="drawer" style="--tint: #3f6fb0" data-drawer>
              <button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-studio" data-front data-autoclic>
                <span class="drawer__card"><span class="drawer__name">Studio</span><span class="drawer__range">G&ndash;L</span></span>
                <span class="drawer__pull" aria-hidden="true"></span>
              </button>
              <ul class="drawer__folders" id="drawer-studio" aria-label="Studio" data-folders>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">About us</span><span class="folder__note">Twelve people, one table</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">People</span><span class="folder__note">Partners and team</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Awards</span><span class="folder__note">From Aalto to Mies</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Careers</span><span class="folder__note">Two places open</span></a></li>
              </ul>
            </li>
            <li class="drawer" style="--tint: #d49b25" data-drawer>
              <button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-journal" data-front data-autoclic>
                <span class="drawer__card"><span class="drawer__name">Journal</span><span class="drawer__range">M&ndash;R</span></span>
                <span class="drawer__pull" aria-hidden="true"></span>
              </button>
              <ul class="drawer__folders" id="drawer-journal" aria-label="Journal" data-folders>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Essays</span><span class="folder__note">On brick, light and time</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">On site</span><span class="folder__note">Notes from the build</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Press</span><span class="folder__note">What others wrote</span></a></li>
              </ul>
            </li>
            <li class="drawer" style="--tint: #8a5a9e" data-drawer>
              <button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-contact" data-front data-autoclic>
                <span class="drawer__card"><span class="drawer__name">Contact</span><span class="drawer__range">S&ndash;Z</span></span>
                <span class="drawer__pull" aria-hidden="true"></span>
              </button>
              <ul class="drawer__folders" id="drawer-contact" aria-label="Contact" data-folders>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Visit</span><span class="folder__note">By appointment</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Write to us</span><span class="folder__note">Replies within a day</span></a></li>
                <li><a class="folder" href="#" data-folder><span class="folder__tab">Newsletter</span><span class="folder__note">Four letters a year</span></a></li>
              </ul>
            </li>
          </ul>
        </div>
      </div>
    </nav>
    <p class="sr" aria-live="polite" data-live></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

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.

59 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 «Il menu a cassetti» da Animorio e adattala al mio sito

Cosa fa

Su una pagina bianca c'è uno schedario d'acciaio verde visto un po' dall'alto e di tre quarti, con il coperchio, il fianco in ombra, lo zoccolo e la sua ombra sul pavimento. Ha quattro cassetti, ognuno con un cartellino battuto a macchina in una cornice d'ottone (Projects A–F, Studio G–L, Journal M–R, Contact S–Z, con le lettere nel colore del cassetto) e una maniglia a conchiglia. Passando col mouse un cassetto esce di qualche centimetro su una molla e torna quando lo si lascia; lo schedario segue appena il puntatore. Premendo un cassetto, questo corre fuori sulle guide e batte sul fermo, la vista si abbassa per guardarci dentro, il cassetto sotto prende la sua ombra, e dalla scatola si alzano una dopo l'altra le cartelline color manila, ognuna più alta di quella davanti, con le linguette spostate a scalinata, bordate in alto col colore del cassetto, e una riga battuta a macchina (Residential, 32 houses, 1998–2026); all'urto del fermo dondolano come cartelle appese. Puntando una cartellina questa si solleva un poco; premendola diventa la pagina corrente e la sua linguetta si fa bianca. Scegliendo un altro cassetto le cartelline riscendono, il cassetto aperto si richiude di colpo, lo schedario sobbalza e gli altri cassetti tremano, poi si apre il nuovo.

Come funziona

Lo schedario in CSS 3D

Tutto è CSS 3D con transform-style: preserve-3d. Lo script costruisce le facce piatte che servono (coperchio, fianco, i listelli d'acciaio intorno ai cassetti, lo zoccolo, il buio dietro ogni fessura col suo pavimento e la sua parete, la scatola di ogni cassetto) e le mette al loro posto col centro e un translate3d, ruotate di 90 gradi quando stanno in piano o di fianco. I frontali dei cassetti sono button veri, le cartelline sono link veri: tutto resta cliccabile e raggiungibile da tastiera.

Le molle e i fermi

Ogni cassetto ha una posizione e una velocità mosse da una molla scritta a mano (SPRING), a passi di 4 millisecondi sul ticker di GSAP, con il passo del fotogramma limitato a 1/30 di secondo. La molla tira oltre il fermo, così il cassetto ci arriva veloce: alle due estremità delle guide la posizione si blocca e la velocità rimbalza smorzata. Un colpo sul fermo chiuso fa sobbalzare lo schedario (una sua molla) e dà una spinta a caso agli altri cassetti; uno sul fermo aperto fa dondolare le cartelline.

Le cartelline a scalinata

Le cartelline stanno nella scatola una dietro l'altra. Aprendo, si alzano a turno ogni STAGGER secondi, ognuna STEP pixel più su di quella davanti, su una molla loro; le linguette si spostano da sinistra a destra lungo il bordo, misurate quando il carattere è arrivato, così sopra il cassetto si legge una scala di nomi. Ogni cartellina è anche un pendolo intorno al suo bordo in basso, spinto dagli urti.

La vista

Lo schedario è ruotato per mostrare il coperchio e il fianco destro e scalato sulla larghezza dello schermo. La vista insegue il puntatore di pochi gradi, e con un cassetto aperto si inclina di più verso il basso (TILT) e sale tanto più quanto più il cassetto è in basso, così lo si vede dentro e resta nell'inquadratura.

Tastiera e lettori di schermo

I cassetti sono button con aria-expanded e aria-controls, le cartelline link con aria-current; le frecce passano da un cassetto all'altro e da una cartellina all'altra, Esc chiude e ridà il fuoco al cassetto, e una pressione fuori dallo schedario lo chiude. Quando si sceglie una cartellina, una riga invisibile (aria-live) dice la pagina nuova ai lettori di schermo, una volta sola.

Valori da cambiare

NomeFileDi partenzaCosa cambia
OUTscript.js150Di quanto esce un cassetto quando si apre, in pixel.
PEEKscript.js20Di quanto esce sotto il puntatore.
SPRINGscript.js[170, 0.5]La molla dei cassetti: quanto è rigida e quanto è frenata (1 = senza rimbalzo).
STEPscript.js30Di quanto ogni cartellina sale più di quella davanti.
STAGGERscript.js0.07I secondi fra una cartellina che sale e la successiva.
TILTscript.js[-15, -27]L'angolo da cui si guarda lo schedario dall'alto: a riposo, e dentro un cassetto aperto.
STARTscript.js-1Il cassetto aperto all'arrivo sulla pagina (-1: nessuno).

Provali nel Playground

Quando usarla

Per il menu di uno studio, un archivio, una casa editrice, un museo o un portfolio con molte sezioni e sottosezioni: dove l'idea di archivio c'entra davvero e il menu può essere la prima cosa che si vede, al centro della pagina o in una pagina di indice.

Sul telefono

Lo schedario si rimpicciolisce sulla larghezza dello schermo, lasciando spazio al cassetto che esce verso sinistra. Senza mouse niente anteprima al passaggio: al tocco il cassetto cede un poco e si apre; le cartelline si toccano sulla linguetta o sul corpo.

Con il movimento ridotto

Niente corsa né molle: un cassetto è chiuso o già tutto fuori, con la vista già inclinata, e le cartelline compaiono al loro posto con una dissolvenza; niente sobbalzi, dondolii né inclinazione col puntatore.

Trappole

  • Fra due facce affiancate in 3D resta spesso un filo di un pixel da cui si vede la pagina: dietro tutte le fessure c'è un'unica parete scura più larga, e pavimenti e pareti delle fessure sono un poco più grandi del necessario, così le giunture mostrano il buio.
  • Un'opacità su un elemento che contiene altri elementi in 3D li appiattisce (preserve-3d smette di valere): nel movimento ridotto si dissolve ogni cartellina, non la lista che le contiene.
  • Con la vista inclinata verso il basso il cassetto più basso, aperto, finiva fuori dall'inquadratura: la vista sale tanto più quanto più il cassetto aperto è in basso.
  • La molla tira il cassetto oltre i fermi (60 pixel oltre quello aperto, 50 oltre quello chiuso): così arriva al fermo ancora veloce e lo colpisce, invece di fermarcisi davanti piano.
  • Le linguette si spostano lungo il bordo in base alla loro larghezza: vanno rimisurate quando il carattere è arrivato, o con quello di riserva l'ultima esce dal bordo della cartellina.

Librerie

GSAP 3.15.0, Familjen Grotesk (font variabile) 5.3.0, Courier Prime 5.3.0.

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

Collaudo

Provata il 4 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.

Tutti i componenti