3D Menu Stack
Quatre liens de menu empilés dans un parent en perspective de 600 px, chacun un peu plus loin et plus pâle que le précédent (0, −10, −20, −30 px ; opacité 1 à 0,7) ; l'entrée survolée, touchée ou atteinte au clavier avance de 20 px, glisse de 10 px vers la droite, pivote de −5° et prend un dégradé indigo-violet avec ombre portée, en 0,3 s — une liste dont la profondeur dit l'ordre, en CSS seul.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. 3D comprend 50 effets, dont 8 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
La racine .fx-0009-root (fond #0a0a0f, 300 px de haut au minimum) définit trois variables : --bg-card: #12121a, --border et --radius-md. Elle centre .menu-stack, une colonne flex (8 px d'écart) qui porte perspective: 600px, et quatre liens <a class="menu-stack-item"> : bloc, texte blanc gras de 14 px, 12 px × 30 px de marge intérieure, fond de carte, bordure fine, transition de 0,3 s sur tout.
La profondeur est écrite entrée par entrée avec :nth-child : la 1re reste à translateZ(0), la 2e recule de 10 px et passe à ×0,98 et 90 % d'opacité, la 3e à −20 px, ×0,96, 80 %, la 4e à −30 px, ×0,94, 70 %. La perspective s'ajoute à l'échelle : mesurées dans Chromium et Firefox, les quatre entrées font 143, 138, 133 et 128 px de large, la pile se resserre vers le bas comme un escalier vu d'en face. Au survol (ou :focus-visible), l'entrée prend translateZ(20px) translateX(10px) rotateY(-5deg), un dégradé #6366f1 → #8b5cf6, une ombre portée vers le bas à gauche et z-index: 10. Cette transformation remplace celle de la ligne :nth-child : plus l'entrée est loin, plus son saut est grand (20 px pour la 1re, 50 px pour la 4e). Mesuré : 4 % des pixels changent au survol de la 2e entrée.
Deux choix d'écriture. Les entrées sont des liens : Tab les atteint, Entrée les suit, et un vrai menu n'a rien à rajouter. Le dégradé du survol est posé sur la couleur de la carte (linear-gradient(…) var(--bg-card)) : un dégradé seul remet la couleur de fond à transparent, et l'entrée qui perd le survol passerait par la transparence pendant 0,3 s, ce qui la ferait pâlir sur une page claire. Les entrées reculées ont une opacité inférieure à 1 : c'est voulu (elles s'effacent avec la distance), mais tout ce qui est posé dessus s'efface avec elles.
Accessibilité
- Mouvement réduit : sous
prefers-reduced-motion: reduce, un bloc limité à.fx-0009-rootne laisse la transition qu'au fond et à l'ombre, et ramène l'entrée choisie àtranslateZ(0): elle passe au premier plan d'un coup, sans glisser ni pivoter ; le dégradé et l'ombre la signalent. Mesuré dans Chromium et Firefox : aucune transition de position en cours, 3,5 % de pixels changés au survol (4 % sans la préférence). - Clavier : quatre liens, atteints avec Tab ; le focus donne exactement l'état du survol (
:focus-visible), plus l'anneau de focus du navigateur. Dans Safari, Tab ne s'arrête sur les liens que si l'option « Appuyer sur Tab pour mettre en évidence chaque élément » est cochée (sinon Option + Tab) — réglage du navigateur, mesuré dans WebKit. - Contraste : texte blanc sur
#12121aà 18,6:1 ; la 4e entrée, à 70 % d'opacité, garde 9,4:1 sur le fond d'origine. L'entrée survolée descend à 4,47:1 sur l'indigo et 4,2:1 sur le violet#8b5cf6, sous le seuil de 4,5:1 pour du texte gras de 14 px : foncez la fin du dégradé (#7c3aeddonne 5,7:1). - Toucher : au doigt, l'entrée touchée prend l'état survolé (mesuré en émulation tactile Chromium et dans Firefox), puis le lien est suivi. Mettez une vraie adresse dans chaque
href.
Compatibilité navigateur
CSS seul (perspective sur le parent, transform sur chaque entrée, :nth-child, :focus-visible), aucune dépendance. Mesuré dans Chromium 151 et Firefox 153 : mêmes largeurs (143 à 128 px), même survol, même comportement en mouvement réduit, 0 erreur. Chaque entrée est transformée seule dans la perspective de son parent, sans plans 3D imbriqués : le WebKit de Playwright (26.5), qui aplatit les scènes en preserve-3d, rend celle-ci comme Chromium (2 % d'écart, dus au lissage du texte).
Sans :focus-visible (navigateur ancien), le focus clavier ne met pas l'entrée en avant : l'anneau du navigateur reste. Sans perspective, les entrées ne reculent plus mais gardent leur réduction (×0,98 à ×0,94) et leur pâleur.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0009-root">
<div class="demo-3d">
<div class="menu-stack"> <!-- perspective: 600px -->
<a class="menu-stack-item" href="#">Menu Item 1</a>
<a class="menu-stack-item" href="#">Menu Item 2</a> <!-- −10 px, ×0,98 -->
<a class="menu-stack-item" href="#">Menu Item 3</a> <!-- −20 px, ×0,96 -->
<a class="menu-stack-item" href="#">Menu Item 4</a> <!-- −30 px, ×0,94 -->
</div>
</div>
</div>
Paiement unique, sans abonnement — le code est à toi pour toujours
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Recul des entrées (CSS — translateZ des quatre :nth-child) |
0, −10, −20, −30 px | Des pas plus grands (0, −25, −50, −75 px) creusent la pile et serrent davantage le bas ; au-delà de −100 px les dernières entrées deviennent petites. Une 5e entrée demande sa propre ligne :nth-child(5). |
Pâleur (CSS — opacity des :nth-child) |
1 ; 0,9 ; 0,8 ; 0,7 | Sous 0,6 le texte de la dernière entrée devient difficile à lire sur fond clair. Mettez 1 partout pour une pile qui recule sans pâlir. |
Mouvement au survol (CSS — transform de :hover, :focus-visible) |
translateZ(20px) translateX(10px) rotateY(-5deg) | rotateY(-10deg) accentue l'effet de porte qui s'ouvre ; retirez translateX pour une entrée qui avance sans glisser. |
Couleurs (CSS — --bg-card, --border et dégradé du survol) |
#12121a ; rgba(255, 255, 255, .08) ; #6366f1 → #8b5cf6 | Gardez var(--bg-card) après le dégradé : c'est la couleur dessous, celle qui évite le passage par la transparence quand le survol s'arrête. |
Perspective (CSS — .menu-stack) |
600 px | 300 px exagère le recul et le pivot ; 1 200 px les aplatit presque. |
Durée (CSS — transition: .3s) |
0,3 s | La même durée sert à l'aller et au retour ; 0,2 s donne un menu plus nerveux. |
FAQ
translateZ(-30px) scale(.94) à translateZ(20px) sans échelle, soit 50 px d'avancée, quand la 1re n'avance que de 20 px. C'est ce qui fait « remonter » une entrée lointaine. Pour des sauts égaux, ajoutez le recul de chaque entrée dans sa règle de survol (par exemple translateZ(-10px) en plus pour la 2e).<a>, atteints au clavier, avec le même relief au focus qu'au survol. Remplacez les href="#" par vos adresses et, pour une navigation principale, entourez la pile d'un <nav aria-label="…">. Gardez quatre à six entrées : au-delà, les dernières reculent tant qu'elles deviennent petites.opacity: 1 partout et laissez le recul et la réduction dire la profondeur.