Créer un composant "Paramètres"

Présentation de base de la création d'un composant de paramètres composé de curseurs et de cases à cocher.

Dans cet article, je souhaite partager mes réflexions sur la création d'un composant de paramètres pour le Web qui soit responsive, compatible avec plusieurs entrées d'appareil et compatible avec tous les navigateurs. Essayez la démo.

Démo

Si vous préférez les vidéos ou si vous souhaitez un aperçu de l'UI/UX de ce que nous créons, voici un tutoriel plus court sur YouTube :

Présentation

J'ai divisé les aspects de ce composant dans les sections suivantes :

  1. Mises en page
  2. Couleur
  3. Plage personnalisée saisie
  4. Saisie de case à cocher personnalisée
  5. Considérations sur l'accessibilité
  6. JavaScript

Mises en page

Il s'agit de la première démonstration de défi d'IUG entièrement basée sur la grille CSS. Voici chaque grille mise en évidence avec les Outils pour les développeurs Chrome pour la grille :

Des contours colorés et des superpositions d'espacement qui permettent d'afficher toutes les cases qui composent la mise en page des paramètres

Juste pour l'écart

La mise en page la plus courante :

foo {
  display: grid;
  gap: var(--something);
}

J'appelle cette mise en page "juste pour l'espacement", car elle n'utilise la grille que pour ajouter des espaces entre les blocs.

Cinq mises en page utilisent cette stratégie. Les voici :

Mises en page de grille verticales mises en évidence par des contours et des espaces remplis

L'élément fieldset, qui contient chaque groupe d'entrées (.fieldset-item), utilise gap: 1px pour créer les bordures fines entre les éléments. Pas de solution de bordure complexe !

Écart comblé
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Astuce de bordure
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

Renvoi à la ligne naturel de la grille

La mise en page la plus complexe s'est avérée être la macro-mise en page, le système de mise en page logique entre <main> et <form>.

Centrer le contenu encapsulé

Flexbox et Grid permettent tous deux d'utiliser align-items ou align-content. Lorsque vous utilisez des éléments d'encapsulation, les alignements de mise en page content répartissent l'espace entre les enfants en tant que groupe.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
}

L'élément principal utilise la propriété abrégée d'alignement place-content: center afin que les enfants soient centrés verticalement et horizontalement dans les mises en page à une et deux colonnes.

Regardez la vidéo ci-dessus pour voir comment le "contenu" reste centré, même si un retour à la ligne s'est produit.

Répéter l'ajustement automatique minmax

<form> utilise une mise en page en grille adaptative pour chaque section. Cette mise en page passe d'une à deux colonnes en fonction de l'espace disponible.

form {
  display: grid;
  gap: var(--space-xl) var(--space-xxl);
  grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
  align-items: flex-start;
  max-width: 89vw;
}

Cette grille a une valeur différente pour row-gap (--space-xl) que pour column-gap (--space-xxl) afin d'apporter une touche personnalisée à la mise en page responsive. Lorsque les colonnes s'empilent, nous voulons un grand espace, mais pas aussi grand que sur un écran large.

La propriété grid-template-columns utilise trois fonctions CSS : repeat(), minmax() et min(). Una Kravets a écrit un excellent article de blog sur la mise en page à ce sujet, qu'elle appelle RAM.

Par rapport à la mise en page d'Una, nous avons ajouté trois éléments spéciaux :

  • Nous transmettons une fonction min() supplémentaire.
  • Nous spécifions align-items: flex-start.
  • Il existe un style max-width: 89vw.

La fonction min() supplémentaire est bien décrite par Evan Minto sur son blog dans l'article Intrinsically Responsive CSS Grid with minmax() and min() (Grille CSS intrinsèquement responsive avec minmax() et min()). Je vous recommande de le lire. La correction d'alignement flex-start consiste à supprimer l'effet d'étirement par défaut, de sorte que les enfants de cette mise en page n'aient pas besoin d'avoir des hauteurs égales, mais puissent avoir des hauteurs naturelles et intrinsèques. La vidéo YouTube présente un bref aperçu de cet ajout d'alignement.

max-width: 89vw mérite une petite analyse dans cet article. Voici la mise en page avec et sans le style appliqué :

Que se passe-t-il ? Lorsque max-width est spécifié, il fournit un contexte, une taille explicite ou une taille définie pour que l'algorithme de mise en page auto-fit sache combien de répétitions il peut insérer dans l'espace. Même s'il semble évident que l'espace est "pleine largeur", conformément à la spécification de la grille CSS, une taille ou une taille maximale définie doit être fournie. J'ai fourni une taille maximale.

Alors, pourquoi 89vw ? Parce que "ça fonctionnait" pour ma mise en page. Avec d'autres membres de l'équipe Chrome, nous cherchons à comprendre pourquoi une valeur plus raisonnable, comme 100vw, n'est pas suffisante et s'il s'agit d'un bug.

Espacement

L'harmonie de cette mise en page provient en grande partie d'une palette d'espacement limitée, sept pour être exact.

:root {
  --space-xxs: .25rem;
  --space-xs:  .5rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2rem;
  --space-xl:  3rem;
  --space-xxl: 6rem;
}

L'utilisation de ces flux s'intègre parfaitement avec la grille, CSS @nest et la syntaxe de niveau 5 de @media. Voici un exemple d'ensemble de styles de mise en page entièrement <main>.

main {
  display: grid;
  gap: var(--space-xl);
  place-content: center;
  padding: var(--space-sm);

  @media (width >= 540px) {
    & {
      padding: var(--space-lg);
    }
  }

  @media (width >= 800px) {
    & {
      padding: var(--space-xl);
    }
  }
}

Une grille avec du contenu centré, modérément espacé par défaut (comme sur mobile). Toutefois, à mesure que l'espace de la fenêtre d'affichage augmente, il s'étend en augmentant la marge intérieure. Le CSS de 2021 est plutôt réussi !

Vous vous souvenez de la mise en page précédente, "just for gap" ? Voici une version plus complète de leur apparence dans ce composant :

header {
  display: grid;
  gap: var(--space-xxs);
}

section {
  display: grid;
  gap: var(--space-md);
}

Couleur

Une utilisation contrôlée de la couleur a permis à cette conception de se démarquer, à la fois expressive et minimaliste. Je procède comme suit :

:root {
  --surface1: lch(10 0 0);
  --surface2: lch(15 0 0);
  --surface3: lch(20 0 0);
  --surface4: lch(25 0 0);

  --text1: lch(95 0 0);
  --text2: lch(75 0 0);
}

Je nomme mes couleurs de surface et de texte avec des chiffres plutôt qu'avec des noms comme surface-dark et surface-darker, car dans une requête média, je vais les inverser, et les termes "clair" et "sombre" n'auront plus de sens.

Je les inverse dans une requête média de préférence comme ceci :

:root {
  ...

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --surface2: lch(100 0 0);
      --surface3: lch(98 0 0);
      --surface4: lch(85 0 0);

      --text1: lch(20 0 0);
      --text2: lch(40 0 0);
    }
  }
}

Il est important d'avoir un aperçu rapide de l'image globale et de la stratégie avant de nous plonger dans les détails de la syntaxe des couleurs. Mais comme je suis allé un peu vite, revenons un peu en arrière.

LCH ?

Sans trop entrer dans les détails de la théorie des couleurs, LCH est une syntaxe orientée vers l'humain, qui s'adapte à la façon dont nous percevons les couleurs, et non à la façon dont nous les mesurons avec des mathématiques (comme 255). Cela lui donne un avantage certain, car les humains peuvent l'écrire plus facilement et d'autres humains seront en phase avec ces ajustements.

Capture d'écran de la page Web pod.link/csspodcast, avec l'épisode &quot;Color 2: Perception&quot; affiché
En savoir plus sur la couleur perceptuelle (et plus encore) dans le podcast CSS

Pour cette démonstration, concentrons-nous sur la syntaxe et les valeurs que je modifie pour créer les thèmes clair et sombre. Examinons une couleur de surface et une couleur de texte :

:root {
  --surface1: lch(10 0 0);
  --text1:    lch(95 0 0);

  @media (prefers-color-scheme: light) {
    & {
      --surface1: lch(90 0 0);
      --text1:    lch(40 0 0);
    }
  }
}

--surface1: lch(10 0 0) se traduit par une luminosité de 10%, une chrominance de 0 et une teinte de 0 : un gris incolore très sombre. Ensuite, dans la requête média pour le mode clair, la luminosité est inversée à 90% avec --surface1: lch(90 0 0);. Voilà l'essentiel de la stratégie. Commencez par modifier la luminosité entre les deux thèmes, en conservant les ratios de contraste requis par la conception ou ce qui peut maintenir l'accessibilité.

L'avantage de lch() ici est que la clarté est orientée vers l'humain, et nous pouvons être sûrs qu'un changement de % sera perçu de manière cohérente comme une différence de %. hsl(), par exemple, n'est pas aussi fiable.

Si vous le souhaitez, vous pouvez en savoir plus sur les espaces colorimétriques et lch(). Il arrive !

Pour le moment, CSS ne peut pas du tout accéder à ces couleurs. Je le répète : nous n'avons pas accès à un tiers des couleurs de la plupart des écrans modernes. Et il ne s'agit pas de n'importe quelles couleurs, mais des couleurs les plus vives que l'écran peut afficher. Nos sites Web sont délavés, car le matériel des écrans a évolué plus rapidement que les spécifications CSS et les implémentations des navigateurs.

Lea Verou

Commandes de formulaire adaptatives avec jeu de couleurs

De nombreux navigateurs proposent des commandes de thème sombre, actuellement Safari et Chromium, mais vous devez spécifier dans le CSS ou le HTML que votre conception les utilise.

L'exemple ci-dessus illustre l'effet de la propriété dans le panneau "Styles" des outils de développement. La démonstration utilise la balise HTML, qui, à mon avis, est généralement un meilleur emplacement :

<meta name="color-scheme" content="dark light">

Pour en savoir plus, consultez color-schemecet article de Thomas Steiner. Il y a bien plus à gagner que des cases à cocher sombres !

CSS accent-color

Il y a eu une activité récente autour de accent-color sur les éléments de formulaire, un style CSS unique qui peut modifier la couleur de teinte utilisée dans l'élément d'entrée du navigateur. Pour en savoir plus, lisez cet article sur GitHub. Je l'ai inclus dans mes styles pour ce composant. Comme les navigateurs le prennent en charge, mes cases à cocher seront plus en phase avec le thème, avec des touches de rose et de violet.

input[type="checkbox"] {
  accent-color: var(--brand);
}

Capture d'écran de Chromium sur Linux montrant des cases à cocher roses

Color pops avec dégradés fixes et focus-within

La couleur ressort mieux lorsqu'elle est utilisée avec parcimonie. Pour y parvenir, j'aime utiliser des interactions d'UI colorées.

La vidéo ci-dessus présente de nombreux niveaux de commentaires et d'interactions de l'interface utilisateur, qui contribuent à donner de la personnalité à l'interaction :

  • Mettre en avant le contexte.
  • Fournir des commentaires sur l'interface utilisateur concernant le "niveau de remplissage" de la valeur dans la plage.
  • Fournir un retour d'interface utilisateur indiquant qu'un champ accepte une saisie.

Pour fournir des commentaires lorsqu'un élément est utilisé, CSS utilise la pseudo-classe :focus-within pour modifier l'apparence de divers éléments. Décomposons le .fieldset-item, c'est très intéressant :

.fieldset-item {
  ...

  &:focus-within {
    background: var(--surface2);

    & svg {
      fill: white;
    }

    & picture {
      clip-path: circle(50%);
      background: var(--brand-bg-gradient) fixed;
    }
  }
}

Lorsqu'un des enfants de cet élément est sélectionné :

  1. Une couleur de surface plus contrastée est attribuée à l'arrière-plan .fieldset-item.
  2. L'élément svg imbriqué est rempli de blanc pour un contraste plus élevé.
  3. Le clip-path <picture> imbriqué s'étend pour former un cercle complet, et l'arrière-plan est rempli d'un dégradé fixe et lumineux.

Période personnalisée

Étant donné l'élément d'entrée HTML suivant, je vais vous montrer comment j'ai personnalisé son apparence :

<input type="range">

Cet élément comporte trois parties que nous devons personnaliser :

  1. Élément/Conteneur de plage
  2. Track
  3. Thumb

Styles d'élément de plage

input[type="range"] {
  /* style setting variables */
  --track-height: .5ex;
  --track-fill: 0%;
  --thumb-size: 3ex;
  --thumb-offset: -1.25ex;
  --thumb-highlight-size: 0px;

  appearance: none;         /* clear styles, make way for mine */
  display: block;
  inline-size: 100%;        /* fill container */
  margin: 1ex 0;            /* ensure thumb isn't colliding with sibling content */
  background: transparent;  /* bg is in the track */
  outline-offset: 5px;      /* focus styles have space */
}

Les premières lignes de CSS sont les parties personnalisées des styles, et j'espère que le fait de les étiqueter clairement vous aidera. Le reste des styles sont principalement des styles de réinitialisation, afin de fournir une base cohérente pour créer les parties complexes du composant.

Styles de pistes

input[type="range"]::-webkit-slider-runnable-track {
  appearance: none; /* clear styles, make way for mine */
  block-size: var(--track-height);
  border-radius: 5ex;
  background:
    /* hard stop gradient:
        - half transparent (where colorful fill we be)
        - half dark track fill
        - 1st background image is on top
    */
    linear-gradient(
      to right,
      transparent var(--track-fill),
      var(--surface1) 0%
    ),
    /* colorful fill effect, behind track surface fill */
    var(--brand-bg-gradient) fixed;
}

L'astuce consiste à "révéler" la couleur de remplissage vive. Pour ce faire, utilisez le dégradé d'arrêt brusque en haut. Le dégradé est transparent jusqu'au pourcentage de remplissage, puis utilise la couleur de la surface de la piste non remplie. Derrière cette surface non remplie se trouve une couleur pleine largeur, qui attend que la transparence la révèle.

Style de remplissage de la piste

Ma conception nécessite JavaScript pour conserver le style de remplissage. Il existe des stratégies CSS uniquement, mais elles nécessitent que l'élément de curseur ait la même hauteur que la piste, et je n'ai pas réussi à trouver une harmonie dans ces limites.

/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')

/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
  const max = slider.getAttribute('max') || 10;
  const percent = slider.value / max * 100;

  return `${parseInt(percent)}%`;
};

/* on page load, set the fill amount */
sliders.forEach(slider => {
  slider.style.setProperty('--track-fill', rangeToPercent(slider));

  /* when a slider changes, update the fill prop */
  slider.addEventListener('input', e => {
    e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
  })
})

Je trouve que cela améliore l'aspect visuel. Le curseur fonctionne parfaitement sans JavaScript. La propriété --track-fill n'est pas obligatoire. S'il n'est pas présent, il n'aura tout simplement pas de style de remplissage. Si JavaScript est disponible, renseignez la propriété personnalisée tout en observant les modifications apportées par l'utilisateur, en synchronisant la propriété personnalisée avec la valeur.

Voici un excellent article sur CSS-Tricks par Ana Tudor, qui présente une solution CSS uniquement pour le remplissage de la piste. J'ai également trouvé cet élément range très inspirant.

Styles de curseur

input[type="range"]::-webkit-slider-thumb {
  appearance: none; /* clear styles, make way for mine */
  cursor: ew-resize; /* cursor style to support drag direction */
  border: 3px solid var(--surface3);
  block-size: var(--thumb-size);
  inline-size: var(--thumb-size);
  margin-top: var(--thumb-offset);
  border-radius: 50%;
  background: var(--brand-bg-gradient) fixed;
}

La plupart de ces styles servent à créer un joli cercle. Là encore, vous voyez le dégradé d'arrière-plan fixe qui unifie les couleurs dynamiques des curseurs, des pistes et des éléments SVG associés. J'ai séparé les styles de l'interaction pour isoler la technique box-shadow utilisée pour la mise en surbrillance au survol :

@custom-media --motionOK (prefers-reduced-motion: no-preference);

::-webkit-slider-thumb {
  …

  /* shadow spread is initally 0 */
  box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);

  /* if motion is OK, transition the box-shadow change */
  @media (--motionOK) {
    & {
      transition: box-shadow .1s ease;
    }
  }

  /* on hover/active state of parent, increase size prop */
  @nest input[type="range"]:is(:hover,:active) & {
    --thumb-highlight-size: 10px;
  }
}

L'objectif était de mettre en avant les commentaires des utilisateurs de manière animée et facile à gérer. En utilisant une ombre de boîte, je peux éviter de déclencher la mise en page avec l'effet. Pour ce faire, je crée une ombre qui n'est pas floue et qui correspond à la forme circulaire de l'élément de curseur. Ensuite, je modifie et j'applique une transition à la taille de l'ombre au pointage.

Si seulement l'effet de mise en surbrillance était aussi simple sur les cases à cocher…

Sélecteurs multi-navigateurs

J'ai constaté que j'avais besoin de ces sélecteurs -webkit- et -moz- pour obtenir une cohérence entre les navigateurs :

input[type="range"] {
  &::-webkit-slider-runnable-track {}
  &::-moz-range-track {}
  &::-webkit-slider-thumb {}
  &::-moz-range-thumb {}
}

Case à cocher personnalisée

Étant donné l'élément d'entrée HTML suivant, je vais vous montrer comment j'ai personnalisé son apparence :

<input type="checkbox">

Cet élément comporte trois parties que nous devons personnaliser :

  1. Élément de case à cocher
  2. Libellés associés
  3. Effet de surbrillance

Élément de case à cocher

input[type="checkbox"] {
  inline-size: var(--space-sm);   /* increase width */
  block-size: var(--space-sm);    /* increase height */
  outline-offset: 5px;            /* focus style enhancement */
  accent-color: var(--brand);     /* tint the input */
  position: relative;             /* prepare for an absolute pseudo element */
  transform-style: preserve-3d;   /* create a 3d z-space stacking context */
  margin: 0;
  cursor: pointer;
}

Les styles transform-style et position préparent le pseudo-élément que nous introduirons plus tard pour styliser la mise en surbrillance. Sinon, il s'agit principalement de petits détails de style de ma part. Je préfère que le curseur soit un pointeur, j'aime les décalages de contour, les cases à cocher par défaut sont trop petites et, si accent-color est compatible, j'intègre ces cases à cocher dans le jeu de couleurs de la marque.

Libellés des cases à cocher

Il est important de fournir des libellés pour les cases à cocher pour deux raisons. Le premier consiste à représenter l'utilisation de la valeur de la case à cocher, pour répondre à la question "Activé ou désactivé pour quoi ?". Deuxièmement, pour l'expérience utilisateur, les utilisateurs Web ont pris l'habitude d'interagir avec les cases à cocher via les libellés associés.

entrée
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
étiquette
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

Sur votre libellé, ajoutez un attribut for qui pointe vers une case à cocher par ID : <label for="text-notifications">. Sur votre case à cocher, doublez le nom et l'ID pour vous assurer qu'elle est détectée par différents outils et technologies, comme une souris ou un lecteur d'écran : <input type="checkbox" id="text-notifications" name="text-notifications">. :hover, :active et d'autres sont disponibles sans frais avec la connexion, ce qui augmente les possibilités d'interaction avec votre formulaire.

Mise en surbrillance de la case à cocher

Je souhaite que mes interfaces soient cohérentes, et l'élément de curseur comporte une mise en surbrillance de la miniature que je souhaite utiliser avec la case à cocher. La vignette a pu utiliser box-shadow et sa propriété spread pour augmenter et réduire l'échelle d'une ombre. Toutefois, cet effet ne fonctionne pas ici, car nos cases à cocher sont carrées, et doivent le rester.

J'ai pu obtenir le même effet visuel avec un pseudo-élément et une quantité regrettable de code CSS complexe :

@custom-media --motionOK (prefers-reduced-motion: no-preference);

input[type="checkbox"]::before {
  --thumb-scale: .01;                        /* initial scale of highlight */
  --thumb-highlight-size: var(--space-xl);

  content: "";
  inline-size: var(--thumb-highlight-size);
  block-size: var(--thumb-highlight-size);
  clip-path: circle(50%);                     /* circle shape */
  position: absolute;                         /* this is why position relative on parent */
  top: 50%;                                   /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
  left: 50%;
  background: var(--thumb-highlight-color);
  transform-origin: center center;            /* goal is a centered scaling circle */
  transform:                                  /* order here matters!! */
    translateX(-50%)                          /* counter balances left: 50% */
    translateY(-50%)                          /* counter balances top: 50% */
    translateZ(-1px)                          /* PUTS IT BEHIND THE CHECKBOX */
    scale(var(--thumb-scale))                 /* value we toggle for animation */
  ;
  will-change: transform;

  @media (--motionOK) {                       /* transition only if motion is OK */
    & {
      transition: transform .2s ease;
    }
  }
}

/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
  --thumb-scale: 1;
}

La création d'un pseudo-élément circulaire est simple, mais le placer derrière l'élément auquel il est associé était plus difficile. Voici l'avant et l'après :

Il s'agit d'une micro-interaction, mais il est important pour moi de conserver la cohérence visuelle. La technique de mise à l'échelle de l'animation est la même que celle que nous avons utilisée ailleurs. Nous définissons une propriété personnalisée sur une nouvelle valeur et laissons CSS la faire passer en fonction des préférences de mouvement. La fonctionnalité clé ici est translateZ(-1px). Le parent a créé un espace 3D et cet enfant pseudo-élément l'a exploité en se plaçant légèrement en arrière dans l'espace Z.

Accessibilité

La vidéo YouTube montre bien les interactions avec la souris, le clavier et le lecteur d'écran pour ce composant de paramètres. Je vais vous présenter quelques détails ici.

Choix d'éléments HTML

<form>
<header>
<fieldset>
<picture>
<label>
<input>

Chacun d'eux contient des conseils et des astuces pour l'outil de navigation de l'utilisateur. Certains éléments fournissent des indications d'interaction, d'autres connectent l'interactivité et d'autres encore aident à façonner l'arborescence d'accessibilité dans laquelle un lecteur d'écran navigue.

Attributs HTML

Nous pouvons masquer les éléments qui ne sont pas nécessaires aux lecteurs d'écran, dans ce cas l'icône à côté du curseur :

<picture aria-hidden="true">

La vidéo ci-dessus illustre le flux du lecteur d'écran sur macOS. Notez que la sélection passe directement d'un curseur à l'autre. En effet, nous avons masqué l'icône qui aurait pu être une étape avant le curseur suivant. Sans cet attribut, l'utilisateur devrait s'arrêter, écouter et passer l'image qu'il ne peut peut-être pas voir.

Le SVG est un ensemble de calculs. Ajoutons un élément <title> pour un titre de survol de la souris sans frais et un commentaire lisible par l'humain sur ce que les calculs créent :

<svg viewBox="0 0 24 24">
  <title>A note icon</title>
  <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>

En dehors de cela, nous avons utilisé suffisamment de code HTML clairement marqué pour que le formulaire fonctionne très bien avec une souris, un clavier, des manettes de jeu vidéo et des lecteurs d'écran.

JavaScript

J'ai déjà expliqué comment la couleur de remplissage de la piste était gérée à partir de JavaScript. Examinons maintenant le code JavaScript associé à <form> :

const form = document.querySelector('form');

form.addEventListener('input', event => {
  const formData = Object.fromEntries(new FormData(form));
  console.table(formData);
})

Chaque fois que l'utilisateur interagit avec le formulaire et le modifie, la console consigne le formulaire en tant qu'objet dans un tableau pour faciliter l'examen avant l'envoi à un serveur.

Capture d'écran des résultats de console.table(), où les données du formulaire sont affichées dans un tableau

Conclusion

Maintenant que vous savez comment j'ai fait, comment feriez-vous ? Cela permet de créer une architecture de composants amusante ! Qui va créer la première version avec des emplacements dans son framework préféré ? 🙂

Diversifions nos approches et découvrons toutes les façons de créer sur le Web. Créez une démo, tweetez-moi les liens, et je l'ajouterai à la section Remix de la communauté ci-dessous.

Remix par la communauté

  • @tomayac pour son style concernant la zone de pointage des libellés des cases à cocher. Cette version ne présente pas d'espace de survol entre les éléments : démo et source.