Boutons✨ Premium

Neumorphic

Bouton gris clair extrudé de sa surface par deux ombres opposées (sombre en bas à droite, blanche en haut à gauche) ; le clic les inverse en creux.

CSSSoft UIActive

Vous aurez accès à la démo interactive avec un compte gratuit.

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Boutons comprend 27 effets, dont 2 gratuits. Découvrir la catégorie →

3 exemples d'usage

Commandes d'un lecteur audio — précédent, lecture, suivant — Neumorphic exemple 1

① Commandes d'un lecteur audio — précédent, lecture, suivant

QuandWidget lecteur d'un site de podcast ou d'une application musicale en thème clair.
PourquoiLe neumorphisme vient de ces maquettes de lecteurs : des touches rondes en relief que l'on enfonce. Le clic en creux reproduit le geste d'un bouton physique.
RéglagesBoutons ronds de 56 px (padding: 0; border-radius: 50%), touche centrale 64 px, ombres 6px / 12px sur les petites touches.
Enregistrer / Annuler — panneau de réglages — Neumorphic exemple 2

② Enregistrer / Annuler — panneau de réglages

QuandFormulaire de préférences avec une paire de boutons d'action en bas.
PourquoiDeux boutons de même matière, hiérarchisés par la couleur du libellé seulement — cohérent avec une interface entièrement grise ; le clic en creux confirme l'envoi.
RéglagesLibellé primaire coloré #4f46e5 et secondaire #555, border-radius: 10px, ombres 6px / 12px pour des boutons plus fins.
Réglage de température — panneau domotique — Neumorphic exemple 3

③ Réglage de température — panneau domotique

QuandTuile thermostat : valeur affichée, touches − et +, un mode.
PourquoiLe rendu « plastique moulé » évoque un appareil physique ; les touches − et + qui s'enfoncent au clic imitent une vraie touche. C'est le contexte où l'inversion inset se lit le mieux.
RéglagesTouches de 52 px, surface #e6e6e6 avec ombres recalculées (#c4c4c4 / #fff), valeur en font-variant-numeric: tabular-nums.

Comment ça marche

Deux box-shadow au repos : 8px 8px 16px #bebebe (sombre, en bas à droite) et -8px -8px 16px #fff (blanche, en haut à gauche). Elles simulent une source lumineuse en haut à gauche frappant une forme en relief. Le background: #e0e0e0 du bouton doit être exactement la couleur de la surface qui l'entoure : l'illusion ne tient que parce que bouton et fond sont identiques, le bord n'étant dessiné que par les ombres.

Au :hover, les décalages passent à 10 px et le flou à 20 px : la forme semble se soulever un peu plus. transition: .2s (toutes propriétés) lisse le changement d'ombres.

Au :active, les deux ombres basculent en inset avec les mêmes valeurs : l'ombre sombre tombe maintenant à l'intérieur, en haut à gauche, et la blanche à l'intérieur, en bas à droite — la forme paraît enfoncée dans la surface. Mêmes couleurs, seul le mot-clé inset change.

Texte #333 sur #e0e0e0, border: none, coins border-radius: 12px hérités de .demo-btn qui donnent sa forme à l'extrusion. Aucun JavaScript.

Accessibilité

  • Repérage du bouton : sa limite n'est dessinée que par des ombres, et #bebebe sur la surface #e0e0e0 ne contraste qu'à 1,4:1 — sous le seuil de 3:1 exigé par WCAG 1.4.11 pour le contour d'un composant d'interface. Une personne malvoyante peut ne pas voir le bouton. Ajoutez une bordure de 1 px (#c8c8c8), un libellé coloré ou des ombres plus marquées.
  • Contraste du texte : #333 sur #e0e0e0 = 9,6:1, niveau AAA. Gardez un libellé sombre — le gris clair courant dans les maquettes neumorphiques tombe vite sous le seuil AA.
  • prefers-reduced-motion : le seul mouvement est une transition d'ombres de 200 ms, négligeable ; transition: none sous la media query ne coûte rien.
  • Focus : le code écrit border: none sans toucher à outline, l'anneau natif reste visible sur gris clair. Si vous le personnalisez, utilisez outline: 2px solid #333; outline-offset: 3px — jamais un focus par ombre, qui se perdrait dans celles du relief.
  • États : le retour « enfoncé » n'existe que pendant l'appui (:active), pas comme état sélectionné persistant. Pour un bouton bascule (lecture/pause, mode nuit), ajoutez aria-pressed et une règle [aria-pressed="true"] reprenant les ombres inset. Cible tactile ≈ 52 px ; sur iOS le soulèvement :hover reste collé après un tap.

Compatibilité navigateur

Requiert des box-shadow multiples avec inset et une transition — tous les navigateurs depuis 2011. Aucun JavaScript, zéro dépendance.

Chrome 10+✓ Complet
Firefox 4+✓ Complet
Safari 5.1+✓ Complet
Edge 12+✓ Complet
Mobile iOS✓ Complet
Android Chrome✓ Complet

Sans transition, les états basculent instantanément. La seule vraie dépendance est le fond : sur une surface d'une autre couleur que #e0e0e0, le relief disparaît et l'ombre blanche se lit comme un halo.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
background (CSS — .btn-neumorphic) = couleur de la surface #e0e0e0 À changer en même temps que le fond du parent : les deux doivent être identiques. Recalculez les ombres : sombre ≈ fond assombri de 15 %, claire = blanc (ou fond éclairci de 10 % sur une surface très claire).
Ombre sombre #bebebe (CSS — box-shadow, 3 occurrences) #bebebe Ombre portée en bas à droite. #b0b0b0 accentue le relief ; atteindre 3:1 avec la surface demanderait ≈ #808080, qui n'est plus du neumorphisme — pour l'accessibilité, ajoutez plutôt une bordure de 1 px.
Décalage / flou 8px 8px 16px (CSS — repos) 8px / 16px Hauteur perçue du relief. 4px / 8px = touche plate ; 12px / 24px = bloc épais. Gardez flou = 2 × décalage.
Survol 10px 10px 20px (CSS — :hover) +2 px de décalage, +4 px de flou Amplitude du soulèvement au survol. Alignez sur le repos pour supprimer l'effet de survol et ne garder que le clic.
inset (CSS — :active) inset 8px 8px 16px / inset -8px -8px 16px Profondeur du creux au clic. 4px / 8px pour une touche fine ; ajoutez transform: translateY(1px) pour accentuer l'enfoncement.
transition (CSS — .btn-neumorphic) .2s Vitesse de bascule relief → creux. .1s = clic sec ; .35s = mousse lente.
border-radius (CSS — .demo-btn) 12px 50% donne les touches rondes d'un lecteur ; 6px, une touche de clavier.

FAQ

Presque toujours parce que le fond n'est pas #e0e0e0. Le relief neumorphique n'existe que si le bouton a exactement la couleur de sa surface : sur un fond blanc l'ombre blanche disparaît et il reste une tache grise ; sur un fond sombre elle devient un halo. Changez le background du bouton et du parent ensemble, puis recalculez les deux ombres.
Même principe avec des valeurs inversées : surface et bouton #2b2b30, ombre sombre #1d1d21 (en bas à droite), ombre claire #39393f (en haut à gauche) — jamais du blanc pur, qui se lirait comme une lueur. Texte en #e5e5e5 (contraste ≈ 11:1).
Oui : copiez la règle :active sous un sélecteur d'état, par exemple .btn-neumorphic[aria-pressed="true"], et basculez l'attribut au clic (btn.setAttribute('aria-pressed', …)). Le creux devient l'état « enfoncé », lisible aussi par les lecteurs d'écran.