Adaptez le formulaire aux petits écrans

HTMLBeginner
Pratiquer maintenant

Introduction

Still & Spoke organise de petits ateliers de poterie le samedi. La page du studio est prête, mais le formulaire a besoin de libellés visibles, de contrôles natifs, d'une note d'assistance conditionnelle et d'une mise en page utilisable au clavier sur écran étroit. Vous effectuerez une véritable réservation locale, au-delà d'un simple message de réussite. Le Study form indépendant fournit un exemple complet avant toute modification.

Vous devez connaître les éléments HTML de base, les sélecteurs et la mise en page CSS, ainsi que les objets, fonctions, sélection du DOM et événements JavaScript. Ce lab présente l'association des libellés, les contraintes du navigateur, les descriptions accessibles, required conditionnel, le focus visible et les règles adaptatives utilisées ici. Un gestionnaire d'envoi et une API locale préparés traitent les requêtes dans ce premier lab ; le suivant construit ce gestionnaire. Les personnes et adresses sont fictives ; aucun courriel ni paiement n'est envoyé. Cet exercice pratique d'utilisabilité n'est pas une certification complète d'accessibilité. Les 50 minutes sont une estimation de l'auteur incluant lecture et erreurs ordinaires.

Utilisez Workspace pour les commandes et Studio pour le site. Les fichiers modifiables sont /home/labex/project/stillspoke/form.html, validity.js et form.css. Conservez les autres fichiers, l'API préparée, les règles de capacité et les visiteurs existants. Chaque lab démarre indépendamment. Le serveur insère le contenu exact de form.html dans l'habillage de la page : il ne complète pas les libellés manquants et ne régénère pas votre travail. Après actualisation, attendez la fin du chargement avant d'utiliser le formulaire. Les libellés du site restent en anglais dans toutes les langues de documentation.

Donnez un nom visible à chaque contrôle

Dans cette étape, utilisez l'exemple terminé au clavier, puis associez chaque contrôle de votre page à son libellé visible et à ses instructions.

Dans Studio, choisissez le lien Study form. Il s'agit d'une navigation dans le site, pas d'un changement de Tab LabEx. L'exemple possède sa propre API et sa base de données ; il ne termine pas votre travail et n'occupe pas vos places. Appuyez sur Tab jusqu'à ce que Your name présente un contour visible. Saisissez Example Guest, appuyez sur Tab, puis saisissez sample@example.test. Avec Tab, atteignez Session, appuyez sur C pour sélectionner Clay, slowly / 10:00 et lisez le titre choisi avant de poursuivre. Ce sélecteur natif accepte le début du texte d'une option. Appuyez sur Tab vers la case d'assistance, Tab vers la note facultative, puis Tab vers Reserve my place. Appuyez une fois sur Enter. Attendez que Submission result affiche Reserved for Example Guest et une véritable Confirmation SS-… délivrée par le serveur. Le message passif d'envoi disparaît. Le focus passe à la section de résultat pour la retrouver facilement.

L'image présente un résultat avec son propre titre et une confirmation réelle. Votre numéro sera différent.

Confirmation réelle dans le formulaire d'exemple indépendant

Choisissez Studio records sur l'exemple. Retrouvez le même nom, la même adresse, l'horaire lisible et le numéro de confirmation. Cette page lit les enregistrements acceptés, pas le texte du résultat affiché dans le navigateur. Choisissez Back to signup, puis Work form pour revenir à votre page. Elle reste incomplète, sans nouvelle réservation de travail ; l'exemple ne compte pas.

Passez à Workspace. cd change le répertoire courant de ce terminal ; un chemin absolu commence par /. pwd affiche ce répertoire. Ces commandes rendent explicite la destination des modifications :

cd /home/labex/project/stillspoke
pwd

Sortie attendue :

/home/labex/project/stillspoke

Les valeurs name du formulaire sont les clés de l'API : name, email, session, support et note. Un id HTML identifie un élément dans la page. La valeur for d'un libellé vise l'id de son champ : cliquer sur le libellé visible ou le lire avec une technologie d'assistance identifie ainsi le contrôle. Ici, Your name utilise for="person", tandis que la clé envoyée est name ; ces attributs ont des rôles différents. Placer la case dans son libellé crée une association implicite. autocomplete="name" et autocomplete="email" indiquent le type d'information que le navigateur peut proposer, sans envoyer de données eux-mêmes. Un texte indicatif disparaît pendant la saisie et ne remplace pas un libellé visible.

required refuse une valeur vide avant l'envoi. type="email" demande au navigateur de refuser une syntaxe incorrecte ; il ne prouve pas à qui appartient l'adresse. minlength="2" exige au moins deux caractères dans le nom. La première option vide impose de choisir une véritable séance. Le value d'une option est son identité stable sur le serveur ; son titre visible s'adresse aux personnes. Ne déduisez pas cette relation de sa position.

aria-describedby contient des ID séparés par des espaces. Il associe chaque champ à son aide permanente et à un paragraphe d'erreur initialement vide. L'aide explique la règle avant l'échec ; l'erreur ajoute le motif après un refus serveur. Utilisez des mots explicites en plus de la couleur. aria-hidden="true" masque uniquement la flèche décorative aux technologies d'assistance. ↗ est une référence numérique HTML : cette source ASCII devient une flèche dans le navigateur. Le paragraphe Sending utilise role="status" pour les annonces passives. aria-labelledby de la section de résultat vise l'ID de son titre et lui donne un nom. L'attribut initial hidden masque le résultat vide jusqu'à ce qu'il y ait quelque chose à afficher. La section distincte a tabindex="-1" : un script peut lui donner le focus sans ajouter d'arrêt dans l'ordre Tab habituel. Nous ne donnons pas le focus à une annonce d'état.

La commande suivante remplace uniquement form.html. cat écrit le texte qui suit ; > remplace le fichier nommé. Le marqueur HTML entre guillemets après << commence un here-document : tout ce qui suit, jusqu'à la ligne contenant seulement HTML, est du contenu littéral. Les guillemets empêchent le shell d'interpréter les caractères HTML. Collez tout le bloc, y compris le marqueur final. Le retour de l'invite signifie que l'écriture est terminée ; aucune touche d'enregistrement séparée n'est nécessaire. Ne collez pas les accents graves Markdown. Cette même méthode servira pour les petits fichiers JavaScript et CSS.

cd /home/labex/project/stillspoke
cat > form.html <<'HTML'
<form id="signup">
  <div class="pair">
    <div class="field">
      <label for="person">Your name (required)</label>
      <input id="person" name="name" required minlength="2" autocomplete="name"
             aria-describedby="name-help name-error">
      <small id="name-help">At least two characters.</small>
      <p class="error" id="name-error"></p>
    </div>
    <div class="field">
      <label for="email">Email (required)</label>
      <input id="email" name="email" type="email" required autocomplete="email"
             aria-describedby="email-help email-error">
      <small id="email-help">Practice address: you@example.test</small>
      <p class="error" id="email-error"></p>
    </div>
  </div>
  <div class="field">
    <label for="session">Session (required)</label>
    <select id="session" name="session" required aria-describedby="session-help session-error">
      <option value="">Choose a time</option>
      <option value="clay-morning">Clay, slowly / 10:00</option>
      <option value="clay-afternoon">Clay, slowly / 14:00</option>
    </select>
    <small id="session-help">Choose a listed time. The afternoon session is full.</small>
    <p class="error" id="session-error"></p>
  </div>
  <label class="check"><input type="checkbox" name="support"> I need seating assistance</label>
  <div class="field">
    <label for="note">Seating note (required when assistance is selected)</label>
    <textarea id="note" name="note" rows="2" aria-describedby="note-help note-error"></textarea>
    <small id="note-help">When assistance is selected, describe the help in at least 5 characters.</small>
    <p class="error" id="note-error"></p>
  </div>
  <button type="submit">Reserve my place <span aria-hidden="true">&#8599;</span></button>
  <p id="progress" role="status"></p>
  <section id="result" aria-labelledby="result-heading" tabindex="-1" hidden>
    <h3 id="result-heading">Submission result</h3>
    <p id="message"></p>
  </section>
</form>
HTML

Revenez dans Studio et actualisez votre page. Lisez les libellés même après saisie. Cliquez sur Email pour voir le focus passer à son champ, puis appuyez sur Tab pour continuer dans l'ordre du document. Avec le formulaire vide, activez Reserve my place : le navigateur doit cibler Your name et expliquer son caractère obligatoire. Saisissez un caractère et réessayez pour observer la longueur minimale. Utilisez un nom tel que Morgan Vale ; saisissez not-an-email pour observer le refus de format de courriel. Il s'agit de messages natifs, pas de réponses HTTP 422 : le navigateur n'a pas envoyé de réservation. Pour corriger, sélectionnez le texte avec Ctrl+A ou Cmd+A lorsque le champ a le focus, puis saisissez le remplacement. Une faute de frappe ne nécessite pas de réinitialiser la VM.

Pour l'instant, la note reste facultative même si la case d'assistance est cochée. Ce sera le prochain comportement à ajouter. La page n'est pas encore adaptée aux écrans étroits. Autocontrôle : les cinq contrôles ont des libellés visibles associés, l'aide reste visible et les valeurs obligatoires vides ne peuvent pas être envoyées.

Faites dépendre la note de la case à cocher

Dans cette étape, rendez la note obligatoire uniquement lorsqu'un visiteur demande une assistance de placement, tout en conservant son texte.

Une case expose le booléen checked : true lorsqu'elle est cochée, false sinon. Un champ ou une zone de texte expose required, qui correspond à sa contrainte HTML. STUDIO est un objet de configuration préparé chargé par scenario.js ; son noteMin vaut 5 pour cet atelier. Lisez cette valeur plutôt que de supposer tous les futurs ateliers identiques. Cette configuration fournit les données du scénario, pas votre règle conditionnelle.

querySelector renvoie le premier élément correspondant à un sélecteur CSS ; [name="support"] et [name="note"] visent ces attributs. Nous sélectionnons les contrôles par leur name d'API. La fonction met à jour deux contraintes natives à chaque changement de case. Dans condition ? first : second, l'opérateur conditionnel choisit first si la condition est vraie, second sinon. La longueur minimale est donc cinq avec assistance, zéro sans assistance. Appeler une fois updateNote() initialise aussi l'état au chargement. L'écouteur change la rappelle lorsque le visiteur bascule la case. Nous changeons les contraintes, pas .value : décocher ne supprime donc pas le brouillon.

Dans Workspace, remplacez validity.js. Le marqueur JS fonctionne comme HTML à l'étape précédente :

cd /home/labex/project/stillspoke
cat > validity.js <<'JS'
const support = document.querySelector('[name="support"]');
const note = document.querySelector('[name="note"]');
function updateNote() {
  note.required = support.checked;
  note.minLength = support.checked ? STUDIO.noteMin : 0;
}
support.addEventListener('change', updateNote);
updateNote();
JS

Revenez dans Studio et actualisez la page. Avec Tab, saisissez un nom d'au moins deux caractères, une adresse valide telle que morgan@example.test, puis Clay, slowly / 10:00. Appuyez sur Space sur I need seating assistance pour cocher. Laissez la note vide et activez Reserve my place. Le navigateur doit maintenant cibler Seating note et demander une valeur. Saisissez near, quittez la note avec Tab, puis réessayez : quatre caractères sont inférieurs aux cinq requis. minlength s'applique au texte saisi par l'utilisateur ; cet exercice le saisit normalement au lieu de l'affecter par script.

Revenez à la case avec Shift+Tab selon les besoins et appuyez sur Space pour décocher. La note est facultative et near reste présent. Recochez et remplacez la note par A seat near the entrance. Conservez ces valeurs pour l'étape suivante ; actualiser efface la saisie non envoyée, mais changer de Tab LabEx laisse cette page ouverte.

Si la case semble sans effet, revenez dans Workspace et affichez le fichier réellement enregistré :

cd /home/labex/project/stillspoke
cat validity.js

Comparez-le au petit bloc précédent, notamment checked et l'appel final updateNote();. Si nécessaire, remplacez le fichier par le bloc complet, puis actualisez Studio. Un script absent ou une faute JavaScript n'est pas la même chose qu'un refus natif de note vide ; l'absence de réservation ne prouve pas le fonctionnement de la contrainte. Autocontrôle : la case change l'obligation, les notes trop courtes ne sont refusées que lorsqu'elle est cochée et le texte existant reste intact.

Gardez le formulaire lisible et son focus visible

Dans cette étape, terminez la mise en page, effectuez une réservation réelle sur votre page et lisez l'enregistrement accepté correspondant.

Un formulaire à deux colonnes doit pouvoir se replier. 1fr 1fr de CSS Grid répartit également l'espace entre nom et courriel ; min-width: 0 autorise le rétrécissement. Avec une largeur maximale de fenêtre de 800 pixels, la media query transforme cette paire en colonne unique. width: 100% avec box-sizing: border-box inclut les espacements internes et bordures dans la largeur disponible. Le sélecteur input:not([type="checkbox"]) exclut les cases de cette règle pleine largeur afin de conserver leur petit carré. Le texte reste disponible sans survol. L'habillage préparé place déjà le récit au-dessus du formulaire sur petit écran ; ces règles font tenir votre formulaire à l'intérieur.

:focus-visible donne un contour visible au focus clavier. La couleur n'est pas le seul signal : mentions obligatoires, erreurs écrites et forme du contour comptent aussi. Des bordures ou ombres de focus clairement équivalentes sont valables ; supprimer toute indication ne l'est pas. [aria-invalid="true"] stylise un champ signalé par le serveur ; .error:empty masque uniquement un paragraphe d'erreur vide, pas un libellé ou une explication nécessaire. overflow-wrap: anywhere permet de couper une longue confirmation ou adresse fictive. La préférence de réduction des mouvements évite d'ajouter des déplacements fluides aux personnes qui demandent moins d'animation ; ce formulaire n'en a pas besoin.

Dans Workspace, remplacez form.css :

cd /home/labex/project/stillspoke
cat > form.css <<'CSS'
form { margin-top: 28px; }
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { min-width: 0; margin-bottom: 18px; }
label { display: block; margin-bottom: 7px; font-size: 13px; font-weight: bold; }
input:not([type="checkbox"]), select, textarea {
  width: 100%; box-sizing: border-box; padding: 11px 12px;
  border: 1px solid #89988a; border-radius: 3px;
  font: inherit; font-size: 15px; color: #243d35; background: #fcfaf5;
}
small { display: block; margin-top: 6px; font-size: 11px; color: #56645a; }
.check { display: flex; gap: 9px; align-items: center; margin: 20px 0; }
.check input { width: 18px; height: 18px; accent-color: #244c3d; }
button {
  padding: 14px 20px; border: 0; border-radius: 3px;
  font: inherit; font-size: 14px; color: #fffdf6; background: #254f41; cursor: pointer;
}
button[type="submit"] { width: 100%; display: flex; justify-content: space-between; }
button:disabled { background: #5b6c5e; cursor: wait; }
:focus-visible { outline: 3px solid #ad4d28; outline-offset: 4px; }
[aria-invalid="true"] { border: 2px solid #9d3327; }
.error { color: #963024; font-size: 12px; margin: 5px 0; }
.error:empty { display: none; }
#progress, #message { font-size: 14px; overflow-wrap: anywhere; }
#result { margin-top: 20px; border-top: 1px solid #c9cebf; padding-top: 12px; }
#result h3 { font-size: 15px; margin: 0 0 8px; }
#records article { border-top: 1px solid #c9cebf; overflow-wrap: anywhere; padding: 12px 0; }
@media (max-width: 800px) { .pair { grid-template-columns: 1fr; gap: 0; } }
@media (prefers-reduced-motion: reduce) { * { scroll-behavior: auto !important; } }
CSS

Revenez dans Studio, actualisez et utilisez votre formulaire. Saisissez Morgan Vale, morgan@example.test, choisissez Clay, slowly / 10:00 avec C, cochez l'assistance avec Space et saisissez A seat near the entrance. Appuyez sur Tab jusqu'au bouton et une fois sur Enter. Attendez la véritable confirmation du gestionnaire préparé. Ce premier lab fournit ce gestionnaire ; vous avez implémenté la sémantique, les contraintes et les styles qui l'entourent. Le suivant explique et construit sa logique de requête et de retour.

Choisissez Studio records et retrouvez le même nom, courriel, horaire et numéro. Conservez Existing Visitor et Avery Reed. Leurs enregistrements sont indépendants du nouveau ; les effacer pour libérer des places sort du périmètre. La capacité est imposée par le serveur, pas un bouton désactivé. Choisissez ensuite Back to signup. La réservation enregistrée persiste même si l'actualisation efface les champs non envoyés.

Réduisez le navigateur ou le panneau Studio vers 390 pixels et examinez aussi une largeur de tablette proche de 768 pixels. Aucun défilement horizontal ne doit être nécessaire ; libellés et aide restent visibles et nom/courriel s'empilent. Parcourez avec Tab : chaque contrôle ciblé doit présenter un indicateur visible. Rétablissez une vue large et vérifiez que la paire peut prendre deux colonnes. Ne masquez pas un champ difficile pour faire tenir le tout.

Si l'ancienne disposition persiste, vérifiez que vous avez écrit form.css dans /home/labex/project/stillspoke, pas base.css, puis actualisez. Un mauvais chemin ne nécessite pas de réinitialiser la VM. Autocontrôle : le formulaire entier est lisible et utilisable sur petits et grands écrans, la réservation réelle apparaît et les visiteurs existants restent présents. Le contrôle lit vos véritables enregistrements et exécute une copie inchangée de vos fichiers sur des données temporaires isolées ; il n'envoie jamais votre formulaire réel à votre place.

Résumé

Vous avez associé libellés visibles, contraintes natives et aide aux contrôles réels, rendu la note conditionnelle sans perdre la saisie et construit une disposition adaptative avec focus clavier visible. Après l'exemple indépendant, vous avez effectué une réservation réelle et comparé sa confirmation aux enregistrements acceptés. Le prochain lab indépendant construit le gestionnaire de requêtes et de retours.