Shake Validation
Le champ e-mail tremble et passe au rouge quand l'adresse est mal formée ; le message reste affiché jusqu'à la correction et l'envoi est bloqué.
Mis à jour le
Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Formulaires comprend 20 effets, dont 2 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
À l'envoi (clic sur le bouton, touche Entrée ou soumission du <form> qui contient le champ), le script teste l'adresse avec la regex ^[^\s@]+@[^\s@]+\.[^\s@]+$, puis les règles natives du champ : required, type="email" et un éventuel pattern. Une adresse refusée pose is-invalid et is-shaking sur .shkv-group : cadre rouge, secousse horizontale de 0,5 s (@keyframes shkv-shake, 4 px d'amplitude) et message « Email invalide » sous le champ.
Le message ne s'efface plus au bout d'une demi-seconde : il reste jusqu'à la frappe suivante. Une adresse acceptée met le cadre en vert (is-valid), lui aussi jusqu'à la frappe suivante ; une adresse fausse tapée ensuite repasse donc bien au rouge. Chaque essai raté rejoue la secousse depuis le début.
Dans un formulaire, le bouton est un vrai type="submit". Adresse fausse : l'envoi est bloqué et la secousse remplace la bulle d'erreur du navigateur. Adresse juste : le formulaire part avec le champ name="email". Hors formulaire, le bouton et la touche Entrée lancent la même vérification sans rien envoyer.
Chaque .fx-0284-root est initialisé à part : deux champs dans la même page ne se pilotent pas entre eux, et rien n'est déclaré sur window.
Accessibilité
- Étiquette réelle : « Adresse e-mail » dans un
<label>masqué visuellement (.shkv-sr), plusautocomplete="email"pour le clavier e-mail sur mobile et le remplissage automatique. - Erreur reliée au champ :
aria-invalid="true"etaria-describedbyvers le message ; ce message vit dans une zonearia-live="assertive"et il est annoncé à chaque essai raté, pas seulement au premier. - Clavier et toucher : Tab atteint le champ puis le bouton (anneau
:focus-visible), Entrée lance la vérification ; au doigt, le bouton répond comme au clic. - Mouvement réduit : sous
prefers-reduced-motion: reduce, ni secousse ni glissement du message ; le cadre rouge, le message et le blocage de l'envoi restent. - Limite : le succès n'est signalé que par le cadre vert. Si votre page doit confirmer l'inscription, affichez un texte après l'envoi.
- Contraste du bouton : texte blanc de 13 px sur le rouge
#dc2626, 4,8:1, et 6,5:1 au survol sur#b91c1c. Mesuré dans Chromium, Firefox et WebKit. Si vous changez--shkv-btn, gardez au moins 4,5:1 avec le texte blanc.
Compatibilité navigateur
JavaScript sans dépendance (environ 3 Ko) et variables CSS. Mesuré le 08/11/2026 dans Chromium, Firefox et WebKit (Playwright) : deux copies indépendantes, envoi bloqué puis accepté dans un vrai <form>, touche Entrée, toucher à 390 px, mouvement réduit, aucune erreur. Versions tirées de @mdn/browser-compat-data : la plus récente des fonctions utilisées est :focus-visible.
Plus ancien (à partir de Chrome 51, Firefox 50, Safari 10, limite fixée par NodeList.forEach) : tout marche sauf l'anneau de focus du bouton. Sans JavaScript, le champ reste un type="email" requis : le navigateur montre sa propre bulle et bloque l'envoi.
Le code
Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :
<div class="fx-0284-root">
<div class="shkv-box">
<div class="shkv-group">
<label class="shkv-field">
<span class="shkv-sr">Adresse e-mail</span>
<input class="shkv-input" type="email" name="email" autocomplete="email" placeholder="Entrez un email valide" required>
</label>
<span class="shkv-msg" aria-live="assertive"><span class="shkv-msg-text" hidden>Email invalide</span></span>
</div>
<button class="shkv-btn" type="submit">Valider</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 |
|---|---|---|
Couleurs d'état (CSS — --shkv-error, --shkv-ok, --shkv-focus sur .fx-0284-root) |
#ef4444 · #10b981 · #6366f1 | Rouge du refus (cadre et message), vert de l'adresse acceptée, contour du champ actif. |
Bouton (CSS — --shkv-btn, --shkv-btn-hover, --shkv-btn-font-size) |
#dc2626 · #b91c1c · .8333rem (13 px environ) | Fond du bouton, fond au survol, taille du libellé. Le libellé lui-même se change dans le HTML. |
Fond, texte et champ (CSS — --shkv-bg, --shkv-text, --shkv-field, --shkv-border) |
#0a0a0f · #fff · blanc à 5 % · blanc à 10 % | Page claire : --shkv-bg:transparent; --shkv-text:#0f172a; --shkv-field:#fff; --shkv-border:#cbd5e1. |
Largeur (CSS — --shkv-width) |
280px | Largeur maximale du bloc ; il se resserre si son conteneur est plus étroit. 100% pour occuper toute la colonne. |
Hauteur du cadre (CSS — --shkv-min-height) |
300px | Hauteur de la zone de démonstration. Mettez 0 dans un vrai formulaire. |
Taille du texte saisi (CSS — --shkv-font-size) |
1rem | Sous 1rem, Safari sur iPhone zoome au focus : gardez 1rem pour un formulaire mobile. |
Écart champ-bouton (CSS — --shkv-gap) |
16px | À 30 px, le message d'erreur passe sous le champ sans toucher le bouton : utile quand le bloc fait moins de 260 px de large. |
Disposition en ligne (classe shkv-inline sur .fx-0284-root) |
absente : bouton centré sous le champ | Champ et bouton sur une même rangée, le bouton prend la hauteur du champ. |
Règle de validation (JS — EMAIL et attributs du champ) |
regex ^[^\s@]+@[^\s@]+\.[^\s@]+$ + required |
Un pattern posé sur le champ (ex. pattern=".+@monentreprise\.fr") s'ajoute à la regex. Le texte d'erreur se change dans .shkv-msg-text. |
FAQ
submit en phase de capture sur le formulaire parent : adresse refusée, il appelle preventDefault() puis stopImmediatePropagation(), et vos propres écouteurs submit ne sont pas appelés. Si vous en avez déclaré un en capture avant le script, testez event.defaultPrevented ou l'attribut aria-invalid du champ.type="email" admet un domaine sans point (réseaux internes). La regex de l'effet exige un point après l'arobase pour attraper l'oubli le plus courant : « .fr », « .com ». Pour un intranet, retirez EMAIL.test(...) dans isValid() et gardez input.validity.valid..fx-0284-root présents au moment où il s'exécute. Pour un bloc injecté plus tard, exécutez-le de nouveau après l'insertion : les racines déjà prêtes portent data-shkv-ready et sont ignorées, rien n'est branché deux fois.