3D Button Press
Un vrai bouton violet posé sur une tranche pleine plus foncée de 8 px, comme une touche : il monte de 2 px au survol (tranche de 10 px) et s'enfonce de 6 px à l'appui (tranche réduite à 2 px, ombre resserrée), en 0,15 s — le bas de la tranche ne bouge pas, c'est la touche qui rentre dans son socle. CSS seul, sans JavaScript, immobile si l'utilisateur réduit les animations.
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-0006-root (fond #0a0a0f, 300 px de haut au minimum, variable --radius-lg définie sur elle) centre un cadre .demo-3d de 280 × 200 px, puis .button-3d-container, qui ne porte qu'une chose : perspective: 500px. Dedans, un vrai <button class="button-3d"> : 16 px × 40 px de marge intérieure, texte blanc gras de 16 px, dégradé vertical #6366f1 → #4f46e5, coins arrondis de 0,75 rem. La tranche n'est pas un élément : c'est une ombre sans flou, box-shadow: #3730a3 0 8px 0, décalée de 8 px vers le bas, qui dessine un socle plein sous le bouton ; une seconde ombre, floue (rgba(0, 0, 0, .4) 0 15px 20px), le pose sur le fond.
Trois états, une transition de 0,15 s sur tout. Au repos, translateZ(20px) dans la perspective de 500 px affiche le bouton à 104 % (156 × 52 px mesurés). Au survol, il monte de 2 px (translateY(-2px)) et la tranche passe à 10 px. À l'appui (:active), il descend de 6 px et recule à translateZ(10px), la tranche tombe à 2 px et l'ombre floue se resserre (5 px / 10 px). Faites le compte : au repos, le bas de la tranche est à 0 + 8 = 8 px sous le bouton ; au survol à −2 + 10 = 8 px ; à l'appui à 6 + 2 = 8 px. Le socle reste en place pendant que la touche monte puis rentre dedans. Mesuré dans Chromium 151 : 1,1 % des pixels changent au survol, 2,9 % à l'appui ; Firefox 153 : 0,9 % et 2,7 %.
Pourquoi une ombre plutôt qu'un pseudo-élément ou une bordure : elle suit l'arrondi du bouton, ne prend aucune place dans la mise en page (les voisins ne bougent pas quand la tranche change d'épaisseur) et se transitionne avec le reste. La perspective ajoute une nuance : le bouton paraît un peu plus proche au repos (×1,04) qu'enfoncé (×1,02). Au clavier, c'est un bouton ordinaire : Tab, Entrée, Espace, et un anneau :focus-visible de 3 px #a5b4fc décalé de 4 px. Dans Chromium, garder Espace appuyé enfonce la touche comme la souris (3,9 % de pixels changés) ; Firefox n'applique pas :active au clavier (0 % mesuré) : le clic part quand même, la touche ne s'enfonce pas.
Accessibilité
- Mouvement réduit : sous
prefers-reduced-motion: reduce, un bloc limité à.fx-0006-rootgardetranslateZ(20px)au survol et à l'appui : la touche ne monte ni ne descend. L'épaisseur de la tranche (8, 10 puis 2 px) et l'ombre marquent encore les deux états. Mesuré dans Chromium et Firefox : transformation identique au repos, au survol et à l'appui ; 0,6 % de pixels changés au survol et 1,2 % à l'appui (contre 1,1 % et 2,9 % sans la préférence). - Clavier : un vrai
<button>, atteint avec Tab et déclenché par Entrée ou Espace. L'anneau de focus#a5b4fcmesure 9,9:1 sur le fond#0a0a0f. Dans Safari, Tab ne s'arrête sur les boutons que si l'option « Appuyer sur Tab pour mettre en évidence chaque élément » est cochée (sinon Option + Tab) : c'est le réglage du navigateur, mesuré dans WebKit, pas un défaut de l'effet. - Contraste : texte blanc gras de 16 px à 4,47:1 en haut du dégradé (
#6366f1) et 6,3:1 en bas (#4f46e5). Le haut est juste sous le seuil de 4,5:1 : pour un texte qui compte, foncez la couleur du haut (#5b5bd6donne 5,4:1). - Toucher : au doigt, le navigateur donne au bouton l'état survolé (mesuré en émulation tactile Chromium et dans Firefox) ; l'enfoncement suit
:active, le temps du contact. Non vérifié sur un vrai iPhone, où Safari n'affiche:activeque dans certaines conditions.
Compatibilité navigateur
CSS seul (box-shadow, transform dans un parent en perspective, :focus-visible), aucune dépendance. Mesuré dans Chromium 151, Firefox 153 et WebKit 26.5 : même rendu au repos, au survol et à l'appui (écarts de 1 % dus au lissage du texte), même immobilité sous mouvement réduit, 0 erreur. Le bouton n'empile pas de plans 3D : le WebKit de Playwright, qui aplatit les scènes en preserve-3d, le rend comme Chromium.
Sans :focus-visible (navigateur ancien), l'anneau de focus par défaut du navigateur s'affiche à la place du liseré violet. Sans transitions, les trois états changent d'un coup : la touche s'enfonce toujours.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0006-root">
<div class="demo-3d">
<div class="button-3d-container"> <!-- perspective: 500px -->
<button class="button-3d">Press Me</button>
</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 |
|---|---|---|
Couleur de la touche (CSS — background de .button-3d) |
#6366f1 → #4f46e5 | Dégradé vertical, clair en haut : il imite la lumière qui tombe sur le dessus de la touche. Gardez la tranche nettement plus foncée que le bas du dégradé, sinon le socle se confond avec le bouton. |
Couleur de la tranche (CSS — première couleur des trois box-shadow) |
#3730a3 | À changer dans les trois règles (repos, :hover, :active), sinon la tranche change de couleur à l'appui. |
Épaisseur de la tranche et course (CSS — 8px, 10px, 2px et translateY) |
8 px au repos ; −2 px / 10 px au survol ; +6 px / 2 px à l'appui | Gardez la somme décalage + tranche égale dans les trois états (ici 8 px) : c'est ce qui laisse le bas du socle immobile. Pour une touche plus épaisse : 12 px au repos, −2 / 14 au survol, +9 / 3 à l'appui. |
Vitesse (CSS — transition: .15s) |
0,15 s | Sous 0,1 s l'appui paraît sec, au-delà de 0,25 s la touche semble molle. La transition porte sur tout : couleur, ombre et position bougent ensemble. |
Profondeur (CSS — perspective: 500px et translateZ) |
500 px ; 20 px au repos, 10 px à l'appui | Le recul de 20 à 10 px rétrécit un peu la touche à l'appui (×1,04 → ×1,02). Retirez translateZ des trois états pour un bouton parfaitement plat : la course verticale suffit. |
Taille (CSS — padding et font-size) |
16 px × 40 px ; 16 px | Le relief tient à toutes les tailles : les scènes l'agrandissent à 22 px × 46 px et 26 px sans rien toucher d'autre. |
FAQ
#8b5cf6 → #6366f1, tranche de 10 px) et ajoute une bascule de 2° au survol et 5° à l'appui, presque invisible : 1,5 % de pixels changés à l'appui contre 2,9 % ici. Celui-ci garde le bas de la tranche immobile, ce qui donne la sensation la plus nette d'une touche qui rentre dans son socle.<button>, Tab l'atteint, Entrée et Espace le déclenchent, et un anneau violet montre le focus. L'enfoncement visible suit :active : au clavier, Chromium l'affiche quand on garde Espace appuyé, Firefox non. Au doigt, Chromium et Firefox donnent l'état survolé au toucher ; sur iPhone, ce n'est pas vérifié.