Les événements focus et blur en JavaScript
Apprenez comment fonctionnent les événements focus et blur en JavaScript, leur différence avec focusin et focusout, et comment les utiliser pour la validation de formulaires et la gestion du focus.
JavaScript vous offre un contrôle précis sur l'élément actuellement focalisé — celui qui reçoit les saisies clavier. Les événements focus et blur vous permettent de réagir au moment où un élément obtient ou perd le focus, ce qui constitue la base de la validation de formulaire en ligne, de la mise en évidence du champ actif, de la création de widgets accessibles au clavier et du guidage des utilisateurs dans un formulaire. Cet article explique ce que sont ces événements, en quoi ils diffèrent de leurs homologues à propagation focusin/focusout, et présente plusieurs modèles pratiques.
Cette page s'appuie sur l'introduction aux événements du navigateur. Si vous devez gérer des événements sur de nombreux éléments à la fois, lisez également l'article sur la propagation et la capture.
Comprendre focus et blur en JavaScript
L'événement focus se déclenche lorsqu'un élément devient la cible active des saisies clavier — l'élément vers lequel pointe document.activeElement. L'événement blur se déclenche lorsque cet élément perd le focus, par exemple lorsque l'utilisateur clique ailleurs, appuie sur Tab, ou que le focus est déplacé par programmation.
Par défaut, seuls les éléments interactifs peuvent recevoir le focus : les liens (<a href>), les contrôles de formulaire (<input>, <textarea>, <select>, <button>) et quelques autres. Pour rendre n'importe quel élément focalisable — un <div>, <span> ou <li> — attribuez-lui un attribut tabindex. Utilisez tabindex="0" pour l'inclure dans l'ordre de tabulation naturel, ou tabindex="-1" pour le rendre focalisable uniquement via un script (element.focus()).
Un point crucial : focus et blur ne se propagent pas. Un écouteur attaché à un élément parent ne se déclenchera pas lorsqu'un champ descendant obtient le focus. Lorsque vous avez besoin d'une délégation d'événements sur un conteneur, utilisez plutôt les contreparties à propagation focusin et focusout — elles se comportent de manière identique mais se propagent vers le haut dans l'arbre DOM.
focus vs. blur vs. focusin vs. focusout
| Événement | Se déclenche quand | Se propage ? |
|---|---|---|
focus | l'élément obtient le focus | Non |
blur | l'élément perd le focus | Non |
focusin | l'élément obtient le focus | Oui |
focusout | l'élément perd le focus | Oui |
Pour un seul élément connu, focus/blur sont les plus simples. Pour un formulaire entier ou une liste de champs, attachez focusin/focusout une seule fois sur le conteneur.
Comment implémenter les événements focus
Pour utiliser l'événement focus, attachez un écouteur à l'élément. L'exemple ci-dessous met en évidence un champ de saisie au moment où il obtient le focus :
<input type="text" id="nameInput" placeholder="Enter Your Name">
<script>
document.getElementById('nameInput').addEventListener('focus', function(event) {
event.target.style.backgroundColor = 'lightblue';
});
</script>Ce code rend le fond du champ de saisie bleu clair lorsqu'il est focalisé, améliorant l'interface utilisateur en indiquant où l'utilisateur est en train de saisir. Pour un simple style visuel, envisagez d'utiliser la pseudo-classe CSS `:focus` comme alternative standard sans JavaScript :
input:focus {
background-color: lightblue;
}Comment implémenter les événements blur
La validation sur blur est l'une des utilisations les plus courantes de ces événements : vous laissez l'utilisateur terminer sa saisie, puis vous vérifiez la valeur lorsqu'il quitte le champ. Voici comment valider une adresse e-mail lorsque le champ perd le focus :
<input type="email" id="emailInput" placeholder="Enter Your Email">
<script>
document.getElementById('emailInput').addEventListener('blur', function(event) {
// Simplified regex for educational purposes
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(event.target.value)) {
alert('Please enter a valid email address.');
event.target.style.backgroundColor = 'salmon';
} else {
event.target.style.backgroundColor = 'lightgreen';
}
});
</script>Ce script vérifie si l'e-mail saisi correspond à un format standard et alerte l'utilisateur si la saisie est invalide. La couleur de fond passe au vert si la valeur est valide et au saumon dans le cas contraire, fournissant ainsi un retour visuel immédiat.
Focaliser des éléments par script
Au-delà de la réaction aux événements, vous pouvez déplacer le focus vous-même avec element.focus() et le retirer avec element.blur(). Cela est utile pour placer le curseur sur le premier champ au chargement de la page, ou pour ramener le focus sur un champ invalide après validation.
<input id="search" placeholder="Search..." />
<button id="go">Focus the search box</button>
<script>
document.getElementById('go').addEventListener('click', () => {
document.getElementById('search').focus();
});
</script>Deux fonctionnalités supplémentaires utiles :
document.activeElementretourne toujours l'élément qui a actuellement le focus (ou<body>si aucun). C'est pratique pour vérifier l'état du focus sans écouteurs.focus({ preventScroll: true })focalise un élément sans le faire défiler dans la vue — utile lorsque vous gérez le défilement vous-même.
Pour un champ qui doit être focalisé dès le chargement de la page, l'attribut HTML autofocus (<input autofocus>) est l'option déclarative qui ne nécessite pas JavaScript.
Utiliser focusin/focusout pour la délégation
Puisque focus et blur ne se propagent pas, attacher un seul écouteur à un formulaire ne capturera pas les changements de focus sur ses champs. Les événements à propagation focusin/focusout résolvent ce problème — vous gérez chaque champ depuis un seul écouteur parent :
<form id="signup">
<input name="email" placeholder="Email" />
<input name="password" type="password" placeholder="Password" />
</form>
<script>
const form = document.getElementById('signup');
form.addEventListener('focusin', (event) => {
event.target.style.outline = '2px solid royalblue';
});
form.addEventListener('focusout', (event) => {
event.target.style.outline = '';
});
</script>L'événement focusout expose également event.relatedTarget — l'élément qui reçoit le focus ensuite — ce qui vous permet de savoir vers où le focus se dirige.
Techniques avancées : gérer plusieurs champs
Lorsqu'un utilisateur remplit correctement un champ de formulaire, vous pouvez automatiquement déplacer le focus vers le champ suivant dès que l'utilisateur quitte le champ actuel. Cela simplifie la saisie du formulaire en éliminant le besoin de clics manuels. Voici comment implémenter ce comportement :
<input type="text" id="firstName" placeholder="First Name" />
<input type="text" id="lastName" placeholder="Last Name" />
<div id="error" style="color: red;"></div> <!-- Display error message here -->
<script>
document.getElementById('firstName').addEventListener('blur', validateFirstName);
function validateFirstName(event) {
const input = event.target;
const errorDiv = document.getElementById('error');
// Allow only letters and spaces, must not be empty
const nameRegex = /^[A-Za-z ]+$/;
if (!nameRegex.test(input.value)) {
errorDiv.textContent = 'Please enter a valid first name.'; // Display error message
input.style.backgroundColor = 'salmon'; // Set background to salmon on invalid input
input.focus(); // Keep focus on the first name input to encourage correction
} else {
input.style.backgroundColor = 'white'; // Reset background to white on valid input
errorDiv.textContent = ''; // Clear error message
document.getElementById('lastName').focus(); // Optionally move focus to the last name input
}
}
</script>Cet exemple déplace automatiquement le focus vers le champ lastName une fois qu'un prénom valide est saisi, améliorant l'expérience utilisateur en réduisant le besoin de clics manuels.
Appeler
input.focus()depuis un gestionnaireblurpeut aller à l'encontre des intentions de l'utilisateur. Si l'utilisateur essayait de cliquer sur un autre élément, refocaliser le champ peut lui donner l'impression d'être piégé. Utilisez ce modèle avec parcimonie, et préférez afficher un message d'erreur que l'utilisateur peut corriger à son propre rythme.
Pièges courants
- Ne vous attendez pas à ce que
focus/blurse propagent. Un écouteur de conteneur pourfocusne se déclenchera jamais ; passez àfocusin/focusoutpour la délégation. blurs'exécute avant que le clic sur un autre contrôle ne soit terminé. Si un gestionnaireblurmasque ou supprime un élément sur lequel l'utilisateur vient de cliquer, le clic peut ne pas être enregistré — vérifiez d'abordevent.relatedTarget.- Les éléments masqués ou
display:nonene peuvent pas recevoir le focus.element.focus()ne fait silencieusement rien sur eux. - Forcer le focus nuit à l'accessibilité lorsque c'est inattendu. Gardez l'ordre de tabulation clavier prévisible et évitez de piéger le focus.
- Pour un style de focus purement visuel, préférez les pseudo-classes CSS
:focus/:focus-visibleplutôt que JavaScript — elles ne nécessitent pas d'écouteurs et fonctionnent avec la navigation au clavier uniquement.
Conclusion
Les événements focus et blur sont la colonne vertébrale des formulaires interactifs et accessibles. Savoir que focus/blur ne se propagent pas (contrairement à focusin/focusout), comment déplacer le focus avec element.focus(), et où tracer la ligne entre JavaScript et la pseudo-classe CSS :focus vous permet de créer des expériences de saisie réactives sans surprendre vos utilisateurs.
Ensuite, explorez les interactions navigateur connexes : les événements clavier, les événements change, input, cut, copy, paste, et la propagation et la capture pour la délégation.