Vai al contenuto
animorio
EN
Tutti i componenti

Il mega menu a tessere

Menu, Hover, 3D, TransizioniSolo CSS, GSAPImpegnativaPeso compresso: Demo 10 KBGSAP 28 KBGratisScarica lo zip

Una barra con Products, Solutions e Resources e un grande pannello sotto, fatto di tessere che si girano in 3D come cartellini: puntando una voce le tessere si ribaltano in un’onda che parte proprio da sotto quella voce e si allarga per il pannello, e sul loro retro compare il mega menu. Passando a un’altra voce l’onda riparte da lì e le tessere girano di nuovo; lasciando la barra si girano via di taglio, sempre in onda.

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 tile mega menu</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/manrope@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the mega menu: a bar with three menus and one panel under it. The panel is a grid of tiles, each a card with two
         faces; each face holds its own slice of the same drawing of the menu. Opening, or going from one menu to
         another, the tiles turn over in a wave that starts right under the menu you point at -->
    <div class="mega" data-mega>
      <nav class="mega__nav" aria-label="Main" data-nav>
        <div class="mega__barwrap">
          <span class="mega__glow" aria-hidden="true" data-glow></span>
          <ul class="mega__bar">
            <li><button class="mega__trigger" type="button" aria-expanded="false" aria-controls="mega-products" data-trigger data-autoclic>Products<svg class="mega__caret" viewBox="0 0 14 14" aria-hidden="true"><path d="M3.5 5.5 7 9l3.5-3.5"/></svg></button></li>
            <li><button class="mega__trigger" type="button" aria-expanded="false" aria-controls="mega-solutions" data-trigger data-autoclic>Solutions<svg class="mega__caret" viewBox="0 0 14 14" aria-hidden="true"><path d="M3.5 5.5 7 9l3.5-3.5"/></svg></button></li>
            <li><button class="mega__trigger" type="button" aria-expanded="false" aria-controls="mega-resources" data-trigger data-autoclic>Resources<svg class="mega__caret" viewBox="0 0 14 14" aria-hidden="true"><path d="M3.5 5.5 7 9l3.5-3.5"/></svg></button></li>
          </ul>
        </div>

        <div class="mega__panel" data-panel>
          <span class="mega__shadow" aria-hidden="true" data-shadow></span>
          <!-- the tiles: built by the script, each face a slice of the menu's picture -->
          <div class="mega__tiles" aria-hidden="true" data-tiles></div>

          <!-- the real menus: the links you click and tab to, shown once the tiles have turned -->
          <div class="mega__content" data-content>
            <section class="mega__section" id="mega-products" aria-label="Products" data-section>
              <div class="mega__col">
                <p class="mega__heading">Platform</p>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #ffe6db; --mark: #e2511f"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 19V11M12 19V5M19 19v-5"/></svg></span><span class="mega__text"><b>Analytics</b><small>See every visit as it happens</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e3f4ea; --mark: #18835a"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M17 3l3 3-3 3M20 6H9a5 5 0 0 0-5 5M7 21l-3-3 3-3M4 18h11a5 5 0 0 0 5-5"/></svg></span><span class="mega__text"><b>Automations</b><small>Let the busywork run itself</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e7e6ff; --mark: #5146d8"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 3h7l4 4v14H7zM14 3v4h4M10 12h5M10 16h5"/></svg></span><span class="mega__text"><b>Reports</b><small>Numbers your whole team can read</small></span></a>
              </div>
              <div class="mega__col">
                <p class="mega__heading">Add-ons</p>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #fff1cf; --mark: #b97a06"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4h14v16H5zM9 9h6M9 13h6M9 17h3"/></svg></span><span class="mega__text"><b>Forms</b><small>Collect answers without code</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e1f0ff; --mark: #1f6fd1"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 7h18v11H3zM3 11h18M7 15h3"/></svg></span><span class="mega__text"><b>Payments</b><small>Take cards in two clicks</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #ffe4ef; --mark: #c8336f"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 13l2.5-8h11L20 13v6H4zM4 13h5l1 2h4l1-2h5"/></svg></span><span class="mega__text"><b>Inbox</b><small>Every message in one place</small></span></a>
              </div>
              <a class="mega__card" href="#" style="--card: #1c1a2b; --glow: #ff7a45">
                <svg class="mega__art" viewBox="0 0 240 120" aria-hidden="true">
                  <rect x="14" y="14" width="140" height="92" rx="10" fill="#26243a"/>
                  <path d="M24 88L48 70L70 76L94 52L118 58L144 32V96H24Z" fill="#ff7a45" fill-opacity="0.2"/>
                  <path d="M24 88L48 70L70 76L94 52L118 58L144 32" fill="none" stroke="#ff7a45" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
                  <rect x="164" y="14" width="62" height="42" rx="10" fill="#26243a"/>
                  <rect x="174" y="36" width="8" height="12" rx="2" fill="#8f86ff"/><rect x="188" y="28" width="8" height="20" rx="2" fill="#8f86ff"/><rect x="202" y="22" width="8" height="26" rx="2" fill="#ffd166"/>
                  <rect x="164" y="64" width="62" height="42" rx="10" fill="#26243a"/>
                  <path d="M176 92a19 19 0 0 1 38 0" fill="none" stroke="#3a3752" stroke-width="6" stroke-linecap="round"/>
                  <path d="M176 92a19 19 0 0 1 30-15.5" fill="none" stroke="#5fd3a1" stroke-width="6" stroke-linecap="round"/>
                </svg>
                <span class="mega__tag">New</span>
                <b>Live dashboards</b>
                <small>Watch your numbers move in real time.</small>
              </a>
            </section>

            <section class="mega__section" id="mega-solutions" aria-label="Solutions" data-section hidden>
              <div class="mega__col">
                <p class="mega__heading">By team</p>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #ffe4ef; --mark: #c8336f"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 10v4h3l6 4V6L7 10zM17 9a4 4 0 0 1 0 6"/></svg></span><span class="mega__text"><b>Marketing</b><small>Campaigns that measure themselves</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #fff1cf; --mark: #b97a06"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 18l5-6 4 3 7-8M15 7h5v5"/></svg></span><span class="mega__text"><b>Sales</b><small>Know which leads are warm</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e1f0ff; --mark: #1f6fd1"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 5h14v10H10l-5 4z"/></svg></span><span class="mega__text"><b>Support</b><small>Answer faster, with context</small></span></a>
              </div>
              <div class="mega__col">
                <p class="mega__heading">By size</p>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e3f4ea; --mark: #18835a"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 20V10M12 10c0-4 3-6 7-6 0 4-3 6-7 6zM12 13c0-3-2.5-5-6-5 0 3.5 2.5 5 6 5z"/></svg></span><span class="mega__text"><b>Startups</b><small>Free until you find your feet</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e7e6ff; --mark: #5146d8"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 8h16v11H4zM9 8V5h6v3M4 13h16"/></svg></span><span class="mega__text"><b>Agencies</b><small>One login for every client</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #ffe6db; --mark: #e2511f"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l7 3v5c0 5-3 8-7 10-4-2-7-5-7-10V6z"/></svg></span><span class="mega__text"><b>Enterprise</b><small>Security reviews, done for you</small></span></a>
              </div>
              <a class="mega__card" href="#" style="--card: #10261f; --glow: #5fd3a1">
                <svg class="mega__art" viewBox="0 0 240 120" aria-hidden="true">
                  <rect x="14" y="14" width="150" height="92" rx="10" fill="#173a2f"/>
                  <g fill="#21503f">
                    <rect x="24" y="26" width="18" height="16" rx="4"/><rect x="47" y="26" width="18" height="16" rx="4"/><rect x="70" y="26" width="18" height="16" rx="4"/><rect x="93" y="26" width="18" height="16" rx="4"/><rect x="116" y="26" width="18" height="16" rx="4"/><rect x="139" y="26" width="18" height="16" rx="4"/>
                    <rect x="24" y="47" width="18" height="16" rx="4"/><rect x="70" y="47" width="18" height="16" rx="4"/><rect x="116" y="47" width="18" height="16" rx="4"/>
                    <rect x="24" y="68" width="18" height="16" rx="4"/><rect x="47" y="68" width="18" height="16" rx="4"/><rect x="93" y="68" width="18" height="16" rx="4"/><rect x="139" y="68" width="18" height="16" rx="4"/>
                  </g>
                  <g fill="#5fd3a1">
                    <rect x="47" y="47" width="18" height="16" rx="4"/><rect x="93" y="47" width="18" height="16" rx="4"/><rect x="139" y="47" width="18" height="16" rx="4"/>
                    <rect x="70" y="68" width="18" height="16" rx="4"/><rect x="116" y="68" width="18" height="16" rx="4"/>
                  </g>
                  <rect x="174" y="14" width="52" height="92" rx="10" fill="#173a2f"/>
                  <rect x="184" y="70" width="12" height="26" rx="3" fill="#2b6b54"/><rect x="204" y="40" width="12" height="56" rx="3" fill="#5fd3a1"/>
                </svg>
                <span class="mega__tag">Case study</span>
                <b>Twice the bookings</b>
                <small>How a six-person studio doubled its calendar in a season.</small>
              </a>
            </section>

            <section class="mega__section" id="mega-resources" aria-label="Resources" data-section hidden>
              <div class="mega__col">
                <p class="mega__heading">Learn</p>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e7e6ff; --mark: #5146d8"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6l8-3 8 3-8 3zM4 6v6l8 3 8-3V6M12 9v12"/></svg></span><span class="mega__text"><b>Guides</b><small>Step by step, from setup to scale</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #ffe6db; --mark: #e2511f"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h13v12H3zM16 10l5-3v10l-5-3"/></svg></span><span class="mega__text"><b>Webinars</b><small>Live sessions with our team</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e3f4ea; --mark: #18835a"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z"/></svg></span><span class="mega__text"><b>Templates</b><small>Start from something that works</small></span></a>
              </div>
              <div class="mega__col">
                <p class="mega__heading">Help</p>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #e1f0ff; --mark: #1f6fd1"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M8 8l-4 4 4 4M16 8l4 4-4 4M13.5 5l-3 14"/></svg></span><span class="mega__text"><b>Docs</b><small>Every feature, explained</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #fff1cf; --mark: #b97a06"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h11v8H8l-4 3zM15 10h5v8l-3-2h-6v-2"/></svg></span><span class="mega__text"><b>Community</b><small>Ask people who have been there</small></span></a>
                <a class="mega__link" href="#"><span class="mega__icon" style="--tint: #ffe4ef; --mark: #c8336f"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12h4l3-7 4 14 3-7h4"/></svg></span><span class="mega__text"><b>Status</b><small>Uptime and incidents, live</small></span></a>
              </div>
              <a class="mega__card" href="#" style="--card: #2a1d10; --glow: #ffc35a">
                <svg class="mega__art" viewBox="0 0 240 120" aria-hidden="true">
                  <path d="M120 30C100 18 66 16 40 22V102C66 96 100 98 120 110Z" fill="#f5e9d2"/>
                  <path d="M120 30C140 18 174 16 200 22V102C174 96 140 98 120 110Z" fill="#fff6e6"/>
                  <path d="M120 30V110" stroke="#d9c4a0" stroke-width="2"/>
                  <g stroke="#cdb48a" stroke-width="3" stroke-linecap="round"><path d="M56 42c18-3 34-2 50 4M56 56c18-3 34-2 50 4M56 70c14-2 26-1 38 3"/><path d="M134 46c16-6 32-7 50-4M134 60c16-6 32-7 50-4M134 74c12-4 24-5 36-4"/></g>
                  <path d="M176 18V48L184 42L192 48V18Z" fill="#ffc35a"/>
                </svg>
                <span class="mega__tag">Field guide</span>
                <b>The small team playbook</b>
                <small>Forty pages on doing more with less, free to download.</small>
              </a>
            </section>
          </div>
        </div>
      </nav>
      <p class="sr" aria-live="polite" data-live></p>
    </div>
  </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.

110 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 mega menu a tessere» da Animorio e adattala al mio sito

Cosa fa

Su una pagina nera una barra color avorio a forma di pillola con tre voci, Products, Solutions e Resources, ognuna con la sua freccetta. Portando il puntatore su Products, sotto la barra nasce un pannello avorio grande, e non arriva tutto insieme: è una griglia di tessere che si girano dal taglio una dopo l’altra, a partire da quella proprio sotto la voce, come un tabellone gigante; mentre girano si sollevano verso chi guarda, si inclinano lontano dall’onda e si scuriscono quando sono di taglio. Quando l’ultima si è fermata c’è il mega menu: due colonne di link con un titolo, Platform e Add-ons, ognuno con un’icona colorata, un nome e una riga di descrizione, e a destra una scheda scura con un piccolo disegno di un cruscotto, l’etichetta New e Live dashboards. Spostandosi su Solutions la pillola chiara dietro la voce scivola e l’onda riparte da Solutions: ogni tessera si ribalta di nuovo e sul retro c’è il nuovo menu, By team e By size con la scheda Twice the bookings; Resources mostra Learn, Help e The small team playbook con un libro aperto. Uscendo dalla barra le tessere si girano via di taglio, in onda dalla voce aperta, e il pannello sparisce. I link si puntano, si cliccano e si raggiungono con Tab e con le frecce.

Come funziona

Una griglia di cartellini a due facce

Il pannello si divide in una griglia adatta alla sua misura (TILE è la misura a cui mira una tessera), con gli spigoli arrotondati soltanto alle tessere d’angolo. Ogni tessera ha due facce in CSS 3D, una girata di 180 gradi, con backface-visibility: hidden, e la griglia ha la sua prospettiva.

Il menu tagliato a pezzi

Ogni faccia contiene una copia del menu grande quanto il pannello, spostata in modo che dalla faccia si veda solo il suo rettangolo: messe insieme, le tessere ricompongono il menu. Le copie non si possono raggiungere con Tab né leggere due volte; il menu vero, con i link, sta sopra le tessere, trasparente finché girano, e si vede appena sono ferme.

Un angolo che cresce soltanto

Il giro di una tessera è un angolo che va sempre avanti: il prossimo multiplo di 180 gradi la cui faccia non è quella in vista. Sulla faccia nascosta si mette il menu nuovo prima che arrivi davanti, anche se l’onda di prima sta ancora girando; una tessera ferma che mostra già il menu giusto non gira. Per chiudere si va al prossimo angolo di taglio, 90 più un multiplo di 180.

L’onda dalla voce

L’onda parte dal punto proprio sotto il centro della voce puntata: il ritardo di ogni tessera è la sua distanza da quel punto divisa per WAVE. Mentre gira, la tessera si alza verso chi guarda col seno dell’angolo, si inclina lontano dall’onda e si scurisce quanto è di taglio; si ferma con un piccolo rimbalzo.

Intento, tastiera e aria

Il puntatore ha un intento fatto di chiamate ritardate di GSAP: un attimo prima di aprire, uno prima di cambiare voce (attraversarne una per andare altrove non la apre) e uno prima di chiudere. Le voci sono pulsanti con aria-expanded e aria-controls; freccia giù o Tab portano dentro il menu, le frecce di lato scorrono la barra, Esc chiude e rende il fuoco, e anche un tocco fuori o il fuoco che esce chiudono.

Valori da cambiare

NomeFileDi partenzaCosa cambia
TILEscript.js96La misura a cui mira una tessera, in pixel (la griglia si adatta al pannello).
FLIPscript.js0.62I secondi che una tessera impiega a girarsi.
WAVEscript.js1500Quanto corre l’onda dalla voce, in pixel al secondo.
LIFTscript.js22Di quanto si alza verso chi guarda una tessera che gira, in pixel.
INTENTscript.js[0.05, 0.12, 0.3]L’intento del puntatore, in secondi: prima di aprire, prima di cambiare voce, prima di chiudere.

Provali nel Playground

Quando usarla

Per la navigazione principale di un sito di prodotto con molte pagine: un SaaS, uno studio, un negozio con categorie. Il ribaltamento dà carattere senza rallentare: le tessere vicine alla voce arrivano subito, e i link veri ci sono appena il pannello è fermo.

Sul telefono

A 390 pixel la barra sta in una riga e il pannello è largo quanto lo schermo, coi link in due colonne e la scheda sotto; la griglia diventa di quattro colonne. Un tocco su una voce apre il suo menu (l’onda parte da lì), un tocco sulla stessa lo chiude, un tocco fuori anche.

Con il movimento ridotto

Niente tessere: il pannello compare in dissolvenza, cambiando voce il menu nuovo sfuma sul vecchio, e chiudendo svanisce. La pillola dietro la voce si sposta senza scivolare.

Trappole

  • Girando ogni volta da 0 a 180 gradi, una tessera presa a metà dall’onda nuova saltava indietro: l’angolo ora cresce soltanto, verso il prossimo multiplo di 180 con l’altra faccia, e il menu nuovo va sempre sulla faccia nascosta.
  • Fra due tessere ferme si vedeva un filo nero della pagina, per l’antialias delle facce in 3D: ogni faccia è mezzo pixel più grande della sua tessera e le posizioni sono arrotondate al pixel.
  • Lasciando ai link veri il loro posto solo a giro finito, un clic durante l’onda si perdeva: il menu vero sta sempre sopra le tessere, trasparente mentre girano, e prende i clic e il fuoco in ogni istante.
  • Le copie del menu nelle tessere avevano link raggiungibili con Tab e venivano lette due volte: niente href, tabindex -1, e tutta la griglia è aria-hidden.
  • Il disegno della scheda usava un gradiente con un id, e nelle copie senza id non si vedeva più: le aree sono a tinta unita con un’opacità.

Librerie

GSAP 3.15.0, Manrope (font variabile) 5.3.0.

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

Collaudo

Provata il 5 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