Les formes en plusieurs étapes sont un bon choix lorsque votre formulaire est grande et a de nombreux contrôles. Personne ne veut faire défiler une forme super longue sur un appareil mobile. En regroupant des contrôles sur une base d'écran par écran, nous pouvons améliorer l'expérience de remplir de longues formes complexes.
Mais à quand remonte la dernière fois que vous avez développé une forme en plusieurs étapes? Cela vous semble-t-il amusant? Il y a tellement de choses à penser et tant de pièces mobiles qui doivent être gérées que je ne vous blâmerais pas de recourir à une bibliothèque de formulaires ou même à un type de widget de formulaire qui vous gère pour vous.
Mais le faire à la main peut être un bon exercice et un excellent moyen de polir les bases. Je vais vous montrer comment j'ai construit mon premier formulaire en plusieurs étapes, et j'espère que vous ne verrez pas seulement à quel point cela peut être accessible, mais peut-être même des zones pour rendre mon travail encore meilleur.
Nous allons traverser la structure ensemble. Nous allons créer une demande d'emploi, ce que je pense que beaucoup d'entre nous peuvent se rapporter à ces derniers jours. Je vais échafauner les HTML, CSS et JavaScript de base d'abord, puis nous examinerons les considérations pour l'accessibilité et la validation.
J'ai créé un repo github pour le code final si vous voulez vous y référer en cours de route.
Obtenez un exemple de codeNotre formulaire de demande d'emploi a quatre sections, dont la dernière est une vue de résumé, où nous montrons à l'utilisateur toutes leurs réponses avant de les soumettre. Pour y parvenir, nous divisons le HTML en quatre sections, chacun identifié avec un ID, et ajoutant une navigation en bas de la page. Je vais vous donner ce HTML de base dans la section suivante.
Navigation de l'utilisateur pour se déplacer à travers des sections signifie que nous inclurons également un indicateur visuel pour quelle étape ils se trouvent et le nombre d'étapes qui restent. Cet indicateur peut être un texte dynamique simple qui se met à jour en fonction de l'étape active ou d'un type d'indicateur de barre de progression plus sophistiqué. Nous ferons le premier pour garder les choses simples et concentrées sur la nature en plusieurs étapes de la forme.,
Nous nous concentrerons davantage sur la logique, mais je fournirai les extraits de code et un lien vers le code complet à la fin.
Commençons par créer un dossier pour tenir nos pages. Ensuite, créez un fichier index.html et collez ce qui suit:
<form > <section > <div > <div > <label for="name">Name <span style="color: red;">*</span></label> <input type="text" name="name" placeholder="Enter your name"> </div> <div > <label for="idNum">ID number <span style="color: red;">*</span></label> <input type="number" name="idNum" placeholder="Enter your ID number"> </div> </div> <div > <div > <label for="email">Email <span style="color: red;">*</span></label> <input type="email" name="email" placeholder="Enter your email"> </div> <div > <label for="birthdate">Date of Birth <span style="color: red;">*</span></label> <input type="date" name="birthdate" max="2006-10-01" min="1924-01-01"> </div> </div> </section> <section > <div > <label for="document">Upload CV <span style="color: red;">*</span></label> <input type="file" name="document" > </div> <div > <label for="department">Department <span style="color: red;">*</span></label> <select name="department"> <option value="">Select a department</option> <option value="hr">Human Resources</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> </select> </div> </section> <section > <div > <label for="skills">Skills (Optional)</label> <textarea name="skills" rows="4" placeholder="Enter your skills"></textarea> </div> <div > <input type="checkbox" name="terms" > <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label> </div> <button type="submit">Confirm and Submit</button> </section> <div > <button type="button" >Previous</button> <span ></span> <button type="button" >Next</button> </div> </form> <script src="script.js"></script>
En regardant le code, vous pouvez voir trois sections et le groupe de navigation. Les sections contiennent des entrées de formulaire et aucune validation de formulaire native. Il s'agit de nous donner un meilleur contrôle de l'affichage des messages d'erreur car la validation du formulaire native n'est déclenchée que lorsque vous cliquez sur le bouton Soumettre.
Ensuite, créez un fichier Styles.css et collez-le:
<form > <section > <div > <div > <label for="name">Name <span style="color: red;">*</span></label> <input type="text" name="name" placeholder="Enter your name"> </div> <div > <label for="idNum">ID number <span style="color: red;">*</span></label> <input type="number" name="idNum" placeholder="Enter your ID number"> </div> </div> <div > <div > <label for="email">Email <span style="color: red;">*</span></label> <input type="email" name="email" placeholder="Enter your email"> </div> <div > <label for="birthdate">Date of Birth <span style="color: red;">*</span></label> <input type="date" name="birthdate" max="2006-10-01" min="1924-01-01"> </div> </div> </section> <section > <div > <label for="document">Upload CV <span style="color: red;">*</span></label> <input type="file" name="document" > </div> <div > <label for="department">Department <span style="color: red;">*</span></label> <select name="department"> <option value="">Select a department</option> <option value="hr">Human Resources</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> </select> </div> </section> <section > <div > <label for="skills">Skills (Optional)</label> <textarea name="skills" rows="4" placeholder="Enter your skills"></textarea> </div> <div > <input type="checkbox" name="terms" > <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label> </div> <button type="submit">Confirm and Submit</button> </section> <div > <button type="button" >Previous</button> <span ></span> <button type="button" >Next</button> </div> </form> <script src="script.js"></script>
Ouvrez le fichier HTML dans le navigateur, et vous devriez obtenir quelque chose comme la disposition à deux colonnes dans la capture d'écran suivante, avec l'indicateur de page actuel et la navigation.
Maintenant, créez un fichier script.js dans le même répertoire que les fichiers HTML et CSS et collez le javascript suivant:
:root { --primary-color: #8c852a; --secondary-color: #858034; } body { font-family: sans-serif; line-height: 1.4; margin: 0 auto; padding: 20px; background-color: #f4f4f4; max-width: 600px; } h1 { text-align: center; } form { background: #fff; padding: 40px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; } .form-group { display: flex; gap: 7%; } .form-group > div { width: 100%; } input:not([type="checkbox"]), select, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; } .form-control { margin-bottom: 15px; } button { display: block; width: 100%; padding: 10px; color: white; background-color: var(--primary-color); border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background-color: var(--secondary-color); } .group-two, .group-three { display: none; } .arrows { display: flex; justify-content: space-between align-items: center; margin-top: 10px; } #navLeft, #navRight { width: fit-content; } @media screen and (max-width: 600px) { .form-group { flex-direction: column; } }
Ce script définit une méthode qui montre et masque la section en fonction des valeurs de forme qui correspondent aux ID des sections de formulaire. Il met à jour Stepinfo avec la section active actuelle du formulaire. Ce texte dynamique agit comme un indicateur de progrès à l'utilisateur.
Il ajoute ensuite une logique qui attend que la page charge et clique sur les événements aux boutons de navigation pour permettre le vélo à travers les différentes sections de formulaire. Si vous actualisez votre page, vous verrez que le formulaire en plusieurs étapes fonctionne comme prévu.
Plongeons plus profondément dans ce que fait le code JavaScript ci-dessus. Dans la fonction UpdateStEpvisibility (), nous masquons d'abord toutes les sections pour avoir une ardoise propre:
const stepInfo = document.getElementById("stepInfo"); const navLeft = document.getElementById("navLeft"); const navRight = document.getElementById("navRight"); const form = document.getElementById("myForm"); const formSteps = ["one", "two", "three"]; let currentStep = 0; function updateStepVisibility() { formSteps.forEach((step) => { document.getElementById(step).style.display = "none"; }); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`; navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block"; } document.addEventListener("DOMContentLoaded", () => { navLeft.style.display = "none"; updateStepVisibility(); navRight.addEventListener("click", () => { if (currentStep < formSteps.length - 1) { currentStep++; updateStepVisibility(); } }); navLeft.addEventListener("click", () => { if (currentStep > 0) { currentStep--; updateStepVisibility(); } }); });
Ensuite, nous montrons la section actuellement active:
formSteps.forEach((step) => { document.getElementById(step).style.display = "none"; });
Ensuite, nous mettons à jour le texte que les indicateurs progressent dans le formulaire:
document.getElementById(formSteps[currentStep]).style.display = "block";`
Enfin, nous masquons le bouton précédent si nous sommes à la première étape et masquons le bouton Suivant si nous sommes à la dernière section:
stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`;
Regardons ce qui se passe lorsque la page se charge. Nous masquons d'abord le bouton précédent car le formulaire se charge de la première section:
navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
Ensuite, nous saisissons le bouton Suivant et ajoutons un événement de clic qui incrémente conditionnellement le nombre d'étapes actuel, puis appelle la fonction UpdateStEpvisibility (), qui met ensuite à jour la nouvelle section à afficher:
document.addEventListener("DOMContentLoaded", () => { navLeft.style.display = "none"; updateStepVisibility();
Enfin, nous attrapons le bouton précédent et faisons la même chose mais à l'envers. Ici, nous diminuons conditionnellement le nombre de pas et appelons le UpdateStEpvisibilité ():
navRight.addEventListener("click", () => { if (currentStep < formSteps.length - 1) { currentStep++; updateStepVisibility(); } });
Avez-vous déjà passé 10 bonnes minutes à remplir un formulaire uniquement pour le soumettre et obtenir de vagues erreurs vous disant de corriger ceci et cela? Je le préfère quand un formulaire me dit tout de suite que quelque chose ne va pas afin que je puisse le corriger avant J'arrive jamais au bouton Soumettre. C'est ce que nous ferons sous notre forme.
Notre principe est d'indiquer clairement quels contrôles ont des erreurs et de donner des messages d'erreur significatifs. Effacer les erreurs lorsque l'utilisateur prend les actions nécessaires. Ajoutons une certaine validation à notre formulaire. Tout d'abord, saisissons les éléments d'entrée nécessaires et ajoutons cela aux existants:
navLeft.addEventListener("click", () => { if (currentStep > 0) { currentStep--; updateStepVisibility(); } });
Ensuite, ajoutez une fonction pour valider les étapes:
<form > <section > <div > <div > <label for="name">Name <span style="color: red;">*</span></label> <input type="text" name="name" placeholder="Enter your name"> </div> <div > <label for="idNum">ID number <span style="color: red;">*</span></label> <input type="number" name="idNum" placeholder="Enter your ID number"> </div> </div> <div > <div > <label for="email">Email <span style="color: red;">*</span></label> <input type="email" name="email" placeholder="Enter your email"> </div> <div > <label for="birthdate">Date of Birth <span style="color: red;">*</span></label> <input type="date" name="birthdate" max="2006-10-01" min="1924-01-01"> </div> </div> </section> <section > <div > <label for="document">Upload CV <span style="color: red;">*</span></label> <input type="file" name="document" > </div> <div > <label for="department">Department <span style="color: red;">*</span></label> <select name="department"> <option value="">Select a department</option> <option value="hr">Human Resources</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> </select> </div> </section> <section > <div > <label for="skills">Skills (Optional)</label> <textarea name="skills" rows="4" placeholder="Enter your skills"></textarea> </div> <div > <input type="checkbox" name="terms" > <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label> </div> <button type="submit">Confirm and Submit</button> </section> <div > <button type="button" >Previous</button> <span ></span> <button type="button" >Next</button> </div> </form> <script src="script.js"></script>
Ici, nous vérifions si chaque entrée requise a une certaine valeur et si l'entrée de l'e-mail a une entrée valide. Ensuite, nous avons réglé le booléen isvalide en conséquence. Nous appelons également une fonction de doucheror (), que nous n'avons pas encore définie.
Collez ce code au-dessus de la fonction validateStep ():
:root { --primary-color: #8c852a; --secondary-color: #858034; } body { font-family: sans-serif; line-height: 1.4; margin: 0 auto; padding: 20px; background-color: #f4f4f4; max-width: 600px; } h1 { text-align: center; } form { background: #fff; padding: 40px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; } .form-group { display: flex; gap: 7%; } .form-group > div { width: 100%; } input:not([type="checkbox"]), select, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; } .form-control { margin-bottom: 15px; } button { display: block; width: 100%; padding: 10px; color: white; background-color: var(--primary-color); border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background-color: var(--secondary-color); } .group-two, .group-three { display: none; } .arrows { display: flex; justify-content: space-between align-items: center; margin-top: 10px; } #navLeft, #navRight { width: fit-content; } @media screen and (max-width: 600px) { .form-group { flex-direction: column; } }
Maintenant, ajoutez les styles suivants à la feuille de style:
const stepInfo = document.getElementById("stepInfo"); const navLeft = document.getElementById("navLeft"); const navRight = document.getElementById("navRight"); const form = document.getElementById("myForm"); const formSteps = ["one", "two", "three"]; let currentStep = 0; function updateStepVisibility() { formSteps.forEach((step) => { document.getElementById(step).style.display = "none"; }); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`; navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block"; } document.addEventListener("DOMContentLoaded", () => { navLeft.style.display = "none"; updateStepVisibility(); navRight.addEventListener("click", () => { if (currentStep < formSteps.length - 1) { currentStep++; updateStepVisibility(); } }); navLeft.addEventListener("click", () => { if (currentStep > 0) { currentStep--; updateStepVisibility(); } }); });
Si vous actualisez le formulaire, vous verrez que les boutons ne vous amènent pas à la section suivante tant que les entrées sont considérées comme valides:
Enfin, nous voulons ajouter une gestion des erreurs en temps réel afin que les erreurs disparaissent lorsque l'utilisateur commence à saisir les informations correctes. Ajoutez cette fonction sous la fonction validateStep ():
formSteps.forEach((step) => { document.getElementById(step).style.display = "none"; });
Cette fonction efface les erreurs si l'entrée n'est plus invalide en écoutant des événements d'entrée et modifiant puis appelant une fonction pour effacer les erreurs. Collez la fonction ClearError () sous la doucheror () une:
document.getElementById(formSteps[currentStep]).style.display = "block";`
Et maintenant, les erreurs sont effacées lorsque l'utilisateur tape dans la valeur correcte:
Le formulaire en plusieurs étapes gère désormais les erreurs gracieusement. Si vous décidez de conserver les erreurs jusqu'à la fin du formulaire, alors à tout le moins, sautez l'utilisateur au contrôle du formulaire errant et montrez une indication du nombre d'erreurs à corriger.
Sous une forme en plusieurs étapes, il est utile de montrer à l'utilisateur un résumé de toutes leurs réponses à la fin avant de se soumettre et de leur offrir une option pour modifier leurs réponses si nécessaire. La personne ne peut pas voir les étapes précédentes sans naviguer en arrière, donc afficher un résumé à la dernière étape donne une assurance et une chance de corriger les erreurs.
Ajoutons une quatrième section au balisage pour maintenir cette vue de résumé et déplacer le bouton Soumettre. Collez-le juste en dessous de la troisième section dans index.html:
stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`;
Ensuite, mettez à jour le formulaire dans votre javascript pour lire:
navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block";
Enfin, ajoutez les classes suivantes à Styles.css:
document.addEventListener("DOMContentLoaded", () => { navLeft.style.display = "none"; updateStepVisibility();
Maintenant, ajoutez ce qui suit en haut du fichier script.js où se trouvent les autres constants:
navRight.addEventListener("click", () => { if (currentStep < formSteps.length - 1) { currentStep++; updateStepVisibility(); } });
puis ajoutez cette fonction dans scripts.js:
navLeft.addEventListener("click", () => { if (currentStep > 0) { currentStep--; updateStepVisibility(); } });
Cela insère dynamiquement les valeurs d'entrée dans la section récapitulative du formulaire, tronque les noms de fichiers et propose un texte de secours pour l'entrée qui n'était pas requise.
Ensuite, mettez à jour la fonction UpdateStEpVisibility () pour appeler la nouvelle fonction:
const nameInput = document.getElementById("name"); const idNumInput = document.getElementById("idNum"); const emailInput = document.getElementById("email"); const birthdateInput = document.getElementById("birthdate") const documentInput = document.getElementById("document"); const departmentInput = document.getElementById("department"); const termsCheckbox = document.getElementById("terms"); const skillsInput = document.getElementById("skills");
Enfin, ajoutez ceci à l'écouteur d'événements DomContent Télélé:
<form > <section > <div > <div > <label for="name">Name <span style="color: red;">*</span></label> <input type="text" name="name" placeholder="Enter your name"> </div> <div > <label for="idNum">ID number <span style="color: red;">*</span></label> <input type="number" name="idNum" placeholder="Enter your ID number"> </div> </div> <div > <div > <label for="email">Email <span style="color: red;">*</span></label> <input type="email" name="email" placeholder="Enter your email"> </div> <div > <label for="birthdate">Date of Birth <span style="color: red;">*</span></label> <input type="date" name="birthdate" max="2006-10-01" min="1924-01-01"> </div> </div> </section> <section > <div > <label for="document">Upload CV <span style="color: red;">*</span></label> <input type="file" name="document" > </div> <div > <label for="department">Department <span style="color: red;">*</span></label> <select name="department"> <option value="">Select a department</option> <option value="hr">Human Resources</option> <option value="it">Information Technology</option> <option value="finance">Finance</option> </select> </div> </section> <section > <div > <label for="skills">Skills (Optional)</label> <textarea name="skills" rows="4" placeholder="Enter your skills"></textarea> </div> <div > <input type="checkbox" name="terms" > <label for="terms">I agree to the terms and conditions <span style="color: red;">*</span></label> </div> <button type="submit">Confirm and Submit</button> </section> <div > <button type="button" >Previous</button> <span ></span> <button type="button" >Next</button> </div> </form> <script src="script.js"></script>
En exécutant le formulaire, vous devriez voir que la section résumé affiche toutes les valeurs entrées et permet à l'utilisateur d'en modifier tout avant de soumettre les informations:
Et maintenant, nous pouvons soumettre notre formulaire:
:root { --primary-color: #8c852a; --secondary-color: #858034; } body { font-family: sans-serif; line-height: 1.4; margin: 0 auto; padding: 20px; background-color: #f4f4f4; max-width: 600px; } h1 { text-align: center; } form { background: #fff; padding: 40px; border-radius: 5px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; } .form-group { display: flex; gap: 7%; } .form-group > div { width: 100%; } input:not([type="checkbox"]), select, textarea { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; } .form-control { margin-bottom: 15px; } button { display: block; width: 100%; padding: 10px; color: white; background-color: var(--primary-color); border: none; border-radius: 4px; cursor: pointer; font-size: 16px; } button:hover { background-color: var(--secondary-color); } .group-two, .group-three { display: none; } .arrows { display: flex; justify-content: space-between align-items: center; margin-top: 10px; } #navLeft, #navRight { width: fit-content; } @media screen and (max-width: 600px) { .form-group { flex-direction: column; } }
Notre formulaire en plusieurs étapes permet désormais à l'utilisateur de modifier et de voir toutes les informations qu'il fournit avant de les soumettre.
Faire des formulaires en plusieurs étapes accessibles commence par les bases: en utilisant un html sémantique. Il s'agit de la moitié de la bataille. Il est suivi de près en utilisant des étiquettes de formulaire appropriées.
D'autres façons de rendre les formulaires plus accessibles, notamment donner suffisamment de place aux éléments qui doivent être cliqués sur de petits écrans et donner des descriptions significatives aux indicateurs de navigation et de progression du formulaire.
offrir des commentaires à l'utilisateur en est une partie importante; Ce n'est pas formidable de faire la rétroaction de l'utilisateur automatique après un certain temps, mais de permettre à l'utilisateur de le rejeter lui-même. Il est également important de prêter attention au contraste et à la police, car ils affectent tous les deux la lisible de votre forme.
Faisons les ajustements suivants à la majoration pour plus d'accessibilité technique:
Dans le fichier de script, remplacez les fonctions de doucheror () et de ClearError () par ce qui suit:
const stepInfo = document.getElementById("stepInfo"); const navLeft = document.getElementById("navLeft"); const navRight = document.getElementById("navRight"); const form = document.getElementById("myForm"); const formSteps = ["one", "two", "three"]; let currentStep = 0; function updateStepVisibility() { formSteps.forEach((step) => { document.getElementById(step).style.display = "none"; }); document.getElementById(formSteps[currentStep]).style.display = "block"; stepInfo.textContent = `Step ${currentStep + 1} of ${formSteps.length}`; navLeft.style.display = currentStep === 0 ? "none" : "block"; navRight.style.display = currentStep === formSteps.length - 1 ? "none" : "block"; } document.addEventListener("DOMContentLoaded", () => { navLeft.style.display = "none"; updateStepVisibility(); navRight.addEventListener("click", () => { if (currentStep < formSteps.length - 1) { currentStep++; updateStepVisibility(); } }); navLeft.addEventListener("click", () => { if (currentStep > 0) { currentStep--; updateStepVisibility(); } }); });
Ici, nous ajoutons et supprimons les attributs qui lient explicitement l'entrée avec sa portée d'erreur et montrons qu'il est dans un état non valide.
Enfin, ajoutons la concentration sur la première entrée de chaque section; Ajoutez le code suivant à la fin de la fonction UpdateStEpVisibility ():
formSteps.forEach((step) => { document.getElementById(step).style.display = "none"; });
et avec cela, le formulaire en plusieurs étapes est beaucoup plus accessible.
Nous y allons, un formulaire en quatre parties en plusieurs étapes pour une demande d'emploi! Comme je l'ai dit en haut de cet article, il y a beaucoup à jongler - à tel point que je ne vous reprocherais pas pour la recherche d'une solution prête à l'emploi.
Mais si vous devez faire grimper à la main un formulaire en plusieurs étapes, j'espère que vous voyez maintenant que ce n'est pas une condamnation à mort. Il y a un chemin heureux qui vous y mène, avec navigation et validation, sans se détourner de bonnes pratiques accessibles.
Et c'est comme ça que je l'ai approché! Encore une fois, j'ai pris cela comme un défi personnel pour voir jusqu'où je pourrais aller, et j'en suis assez content. Mais je serais ravi de savoir si vous voyez des opportunités supplémentaires pour rendre cela encore plus attentif à l'expérience utilisateur et attentionné à l'accessibilité.
Voici quelques liens pertinents auxquels j'ai fait référence lors de la rédaction de cet article:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!