Submit Button
Un bouton d'envoi qui se transforme en spinner circulaire pendant le chargement, puis en coche de confirmation — trois états morphiques enchaînés en CSS et JavaScript, sans rechargement de page.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Hover comprend 48 effets, dont 5 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
La racine .fx-0363-root (250 px de haut, fond rgb(26, 26, 36)) centre un bouton .mi-submit-btn de 200×52 px. Le bouton contient trois enfants superposés : .mi-submit-text (libellé Envoyer), .mi-submit-loader (conteneur du spinner), et .mi-submit-check (SVG de la coche). En CSS, les états .loading et .success sur le bouton pilotent trois changements simultanés : la largeur (200 px → 52 px pour le spinner et la coche), le rayon de bordure (14 px → 26 px pour former un cercle), et l'opacité de chaque couche.
Le spinner .mi-submit-spinner est un div de 24 px avec une bordure dont un quart est coloré et le reste transparent ; il tourne par @keyframes miSpinnerRot (0,8 s linéaire infini). La coche est un SVG polyline dont le tracé passe de 0 % à 100 % via stroke-dashoffset et @keyframes miCheckDraw (0,3 s). La transition de forme dure 0,4 s avec ease-in-out ; la transition vers l'état coche démarre 100 ms après pour que le morphing soit terminé quand la coche apparaît.
Le script est déclenché au clic sur le bouton. Il vérifie que le bouton n'est pas déjà en chargement ou en succès, ajoute .loading et les attributs aria-busy="true" et aria-disabled="true". Après 1 500 ms, il retire .loading, ajoute .success. Après 1 800 ms supplémentaires, il retire .success et nettoie les attributs ARIA. Dans votre intégration réelle, remplacez les délais fixes par la réponse de votre appel serveur.
Accessibilité
- Clavier : le composant est un vrai
<button>; Tab l'atteint, Espace ou Entrée le déclenche. L'état de chargement désactive le bouton viaaria-disabledpour prévenir les doubles soumissions. - État de chargement annoncé :
aria-busy="true"est ajouté pendant le chargement. Les lecteurs d'écran qui interprètent cet attribut sur un bouton annoncent que l'action est en cours ; testez avec NVDA et VoiceOver car les implémentations varient. - Mouvement réduit : sous
prefers-reduced-motion: reduce, le morphing de forme (changements dewidthetborder-radius) est supprimé, l'animation du spinner est arrêtée, et le tracé de la coche est instantané. L'état de chargement et de succès restent indiqués par les changements de couleur et l'apparition du spinner/de la coche. - Toucher : le bouton répond normalement aux événements tactiles. Sa cible de 200×52 px est large et facile à atteindre au doigt.
Compatibilité navigateur
CSS (transitions width, border-radius, opacity, animations spinner et coche) + 0,5 Ko de JavaScript (classList, setAttribute, setTimeout), aucune dépendance. Vérifié dans Chromium 151 : morphing en 3 états, aria-busy mis à jour, deux copies indépendantes, mouvement réduit sans morphing, 0 erreur. Les captures d'aperçu montrent l'animation rejouée en boucle automatique par le code de scène : ce comportement n'est pas inclus dans le code vendu.
Sans JavaScript, le bouton est cliquable mais ne change pas d'état. Sans transitions CSS, les trois couches apparaissent et disparaissent instantanément sans morphing.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0363-root">
<div class="mi-submit-scene">
<button class="mi-submit-btn">
<span class="mi-submit-text">Envoyer</span>
<span class="mi-submit-loader">
<div class="mi-submit-spinner"></div>
</span>
<span class="mi-submit-check">
<svg viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</span>
</button>
</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 du bouton au repos (CSS — background de .mi-submit-btn) |
Violet #6366f1 |
Adaptez à la couleur primaire de votre charte. La couleur de succès (.mi-submit-btn.success) et la couleur de chargement (.mi-submit-btn.loading) peuvent être modifiées indépendamment. |
Durée du chargement simulé (JS — premier setTimeout) |
1 500 ms | Dans une intégration réelle, remplacez le setTimeout par la résolution de votre promesse réseau : appelez l'entrée en état .success dans le .then() ou le callback de succès. |
Libellé du bouton (HTML — texte dans .mi-submit-text) |
Envoyer | Remplacez par Valider, S'inscrire, Confirmer, etc. Le morphing en cercle fonctionne quelle que soit la longueur du libellé, car la largeur de départ est fixe (200 px). |
Durée d'affichage de la coche (JS — deuxième setTimeout) |
1 800 ms | Réduisez à 1 000 ms pour un retour rapide ; augmentez à 3 000 ms pour laisser le temps à l'utilisateur de lire un message de confirmation affiché à côté. |
FAQ
setTimeout et déclenchez votre requête (fetch, XMLHttpRequest). Dans le callback de succès, passez à l'état .success ; dans le callback d'erreur, retirez .loading et restaurez le bouton à son état initial en retirant aussi aria-busy et aria-disabled..fx-0363-root indépendamment. Chaque bouton a son propre cycle d'états. Lancer une soumission sur l'un n'affecte pas les autres..loading ou .success : si oui, il ignore le clic. Combiné à aria-disabled="true", cela empêche les soumissions multiples pendant le traitement.