1 points par GN⁺ 1 시간 전 | 1 commentaires | Partager sur WhatsApp
  • Les listes HTML doivent être choisies en fonction de leur sens et de leur mode d’interaction, plutôt que de leur apparence visuelle, et se divisent en listes de contrôle, ordonnées, descriptives, de menu et non ordonnées
  • Pour des choix fixes, il faut utiliser <select>/<option>, tandis que <datalist> convient à la saisie avec suggestions ; il faut aussi distinguer le comportement de multiple, optgroup, size et value
  • <ol> s’utilise pour les procédures, événements et continuums dont le sens change si l’on modifie l’ordre, et reversed n’inverse que la numérotation sans changer l’ordre réel des éléments
  • <dl> s’est étendu en HTML5 au-delà de la liste de définitions pour devenir une liste descriptive, adaptée aux paires clé-valeur comme les termes-valeurs, les métadonnées ou le débogage JSON
  • <menu> sert aux listes de commandes comme des boutons d’outils ; son sens et son contenu autorisé diffèrent de nav, tandis que les autres listes générales relèvent de <ul>

Listes de contrôle : <select>/<option> et <datalist>

  • Il est aussi possible de construire des listes interactives dans un formulaire
  • Les choix fixes avec <select> et <option>

    • Si l’utilisateur doit uniquement pouvoir choisir parmi les éléments de la liste, on utilise <select> et <option>
    • L’exemple de liste de langues place des <option> comme Select a Language, English, French, Spanish, Portuguese dans <select name="languages">
    • Un <select> par défaut ne permet de choisir qu’une seule option
    • Pour autoriser la sélection de plusieurs éléments, il faut ajouter l’attribut multiple
      • Avec multiple, l’affichage de la liste change et toutes les options sont visibles ; l’utilisateur peut sélectionner plusieurs éléments avec Shift ou Cmd + clic
      • Avec de vrais éléments select et option, la sémantique native du navigateur gère cela sans qu’il soit nécessaire d’ajouter manuellement aria-multiselectable à un élément de liste avec role="listbox"
  • Regrouper des options liées avec <optgroup>

    • Si l’on veut regrouper les langues par familles linguistiques, on groupe la liste d’options avec <optgroup>
    • L’exemple crée des <optgroup> avec le label Germanic, Romance, Celtic et y place English, French, Spanish, Portuguese, Irish, Welsh
    • Pour empêcher la sélection d’un sous-groupe donné, il faut ajouter l’attribut disabled à l’<optgroup> concerné
    • Dans l’exemple, le groupe Celtic reçoit disabled, ce qui désactive le groupe contenant Irish et Welsh
  • Améliorer avec les fonctionnalités natives de HTML

    • S’il faut une séparation visuelle entre les groupes, on peut utiliser <hr> autorisé dans <select>
    • L’attribut size contrôle le nombre d’éléments affichés en même temps, ce qui est utile pour les longues listes
    • Quand on combine size et optgroup, les libellés de groupe occupent eux aussi de l’espace d’affichage
    • L’exemple ajoute à <select name="languages" size="4" multiple> les groupes Germanic, Romance, Celtic, Afroasiatic, des <hr /> entre eux, ainsi que Hebrew et Arabic

Listes de suggestions : <datalist>

  • Si l’utilisateur ne doit pas obligatoirement choisir uniquement dans la liste mais qu’on veut suggérer des éléments, on utilise <datalist>
  • <datalist> se relie en deux étapes
    • on crée un <datalist> et on lui attribue un id
    • on met ensuite cette valeur d’id dans l’attribut list du <input> correspondant
  • Dans l’exemple de suggestion de langues, <datalist id="languages"> contient les options English, French, Spanish, Portuguese, Irish, Welsh, Hebrew, Arabic, puis est relié au champ de saisie via <input name="language" list="languages">
  • Fonctionnement de <option value>

    • La valeur par défaut de <option> est le texte qu’il contient et, s’il existe, l’attribut value remplace cette valeur par défaut, tandis que le texte agit comme un libellé
    • Dans <select>, cela pose peu de problème puisque l’utilisateur ne voit que le texte, mais dans <datalist>, l’utilisateur peut voir le libellé, le choisir, puis voir value inséré dans le champ, ce qui peut être déroutant
    • Dans l’exemple, si l’on choisit <option value="cy">Welsh</option>, l’utilisateur voit Welsh mais cy est inséré dans le champ
    • Avec <datalist>, il faut partir du principe que la valeur insérée n’est pas le libellé mais bien value
  • Combinaison avec plusieurs types d’entrée

    • <datalist> ne sert pas seulement aux options textuelles ; il peut aussi être utilisé avec d’autres types d’input
    • L’exemple de sélection par semaine relie <datalist id="preferred-weeks"> à <input type="week" name="week" id="camp-week" min="2026-W2" max="2026-W51" list="preferred-weeks" />
    • Les semaines suggérées sont 2026-W22, 2026-W23, 2026-W24, 2026-W25
  • Combinaison avec <input type="range">

    • <datalist> n’est pas limité aux chaînes de caractères et fonctionne aussi avec des valeurs numériques ; il peut donc être combiné à un champ range pour créer des points étiquetés sur une plage
    • L’exemple de pourcentage de pourboire relie <datalist id="recommended-tips"> à <input type="range" name="tips" id="tips" min="0" max="50" step="1" list="recommended-tips" /> et ajoute les libellés 10%, 18%, 30%, 45%
    • Dans les navigateurs de type Chrome, @supports (x: attr(x type(percentage))) permet de lire la valeur label via attr(), de déclarer la valeur en pourcentage via type(), puis de positionner les options en position: absolute
    • L’approche pour Firefox utilise @supports not (x: attr(x type(percentage))), et la valeur est affichée avec ::before
    • Cette méthode ne garantit pas que tous les navigateurs se comportent de la même manière ni qu’ils affichent la même chose à l’écran

Listes ordonnées : <ol>

  • Pour un ensemble d’éléments qui doivent être lus dans un ordre précis, on utilise <ol>
  • Le critère n’est pas de savoir si un numéro doit apparaître à côté des éléments, mais si le sens de la liste change quand on modifie leur ordre
  • Les collections adaptées à <ol> sont les algorithmes, les suites d’événements, les éléments sur un continuum croissant ou décroissant, les recettes et les listes alphabétiques
  • L’exemple de recette de banana bread exprime avec <ol> l’ordre suivant : préchauffer le four et graisser le moule, mélanger les ingrédients, verser la pâte, cuire 60 minutes ou jusqu’à ce qu’un cure-dent ressorte propre, puis laisser refroidir sur une grille
  • Une liste alphabétique d’ingrédients relève aussi de <ol>, puisqu’elle suit le continuum de l’alphabet, avec l’ordre baking soda, bananas, brown sugar, butter, eggs, flour, salt
  • Imbrication de listes ordonnées et non ordonnées

    • Une liste ordonnée bien structurée doit permettre de comprendre l’ordre des actions même sans voir le rendu du navigateur
    • L’exemple de recette utilise <ol> pour les étapes principales ; à l’intérieur d’une étape, les éléments dont l’ordre n’a pas d’importance sont placés dans <ul>, et les sous-étapes où l’ordre compte à nouveau dans <ol>
    • La structure conserve l’ordre principal de Prepare, Mix, Pour, Bake, Cool, tandis que les éléments parallèles dans Prepare et Bake sont représentés avec <ul>, et les procédures internes de Mix et Cool avec <ol>
  • reversed

    • L’attribut reversed fait passer la numérotation d’un ordre croissant à un ordre décroissant
    • Il ne modifie pas l’ordre réel des éléments de la liste
    • Il peut s’utiliser pour une liste d’ingrédients et de quantités présentée du plus au moins, comme most to least
    • L’exemple met dans <ol reversed> les éléments eggs (2), flour (2 cups), bananas (2) (mashed), brown sugar (¾ cup), butter (½ cup), baking soda (1 teaspoon), salt (¼ teaspoon)
  • Inverser réellement l’ordre des éléments avec JavaScript

    • Pour réellement inverser la liste, on peut réorganiser les enfants li dans l’ordre inverse avec JavaScript, puis basculer l’attribut reversed
    • La fonction d’exemple transforme le résultat de list.querySelectorAll('li') en tableau, applique .reverse(), vide la liste avec list.innerHTML = '', puis réattache les éléments avec list.append(...children)
    • Elle appelle ensuite list.toggleAttribute('reversed')
    • L’événement d’exemple déclenche l’inversion au double-clic via orderedList.addEventListener('dblclick', (evt) => { reverseList(orderedList) })
  • start

    • L’attribut start sert à conserver la continuité de la numérotation lorsqu’on découpe une très grande liste en plusieurs listes ordonnées au lieu d’une seule
    • Dans l’exemple de recette de banana bread, Prepare reste en ul, Mix utilise <ol start=2>, Pour utilise <ol start=5>, et Cool utilise <ol start=7> afin de préserver la continuité des numéros d’étapes
    • Même s’il existe au milieu une section exprimée en liste non ordonnée comme 6: Bake, la liste ol de Cool peut reprendre à start=7 pour maintenir le fil de numérotation de l’ensemble de la procédure

Listes descriptives : <dl>, <dt>, <dd>

  • Une liste descriptive (description list) est un type de liste qui évite de forcer tout contenu dans ol ou ul
  • Les listes de définition en HTML 4

    • En HTML 4, on parlait non pas de description list mais de liste de définitions (definition list), pensée pour un usage plus étroit consistant à fournir des définitions
    • La structure se composait de <dt> pour le terme à définir et de <dd> pour la définition, et pour une utilisation sémantiquement exacte, le terme défini était enveloppé dans <dfn>
    • L’exemple relie throw et yeet à une même définition, et associe séparément une définition à no cap et bet
      <dl>
        <dt><dfn>throw</dfn></dt>
        <dt><dfn>yeet</dfn></dt>
        <dd>Verb. To discard at a high velocity</dd>
        <dt><dfn>no cap</dfn></dt>
        <dd>Interjection. Expresses authenticity and truthfulness, sometimes surprise.</dd>
        <dt><dfn>bet</dfn></dt>
        <dd>Interjection. Expresses agreement and affirmation.</dd>
      </dl>
    
  • Un sens élargi en HTML5

    • En HTML5, cela devient une liste descriptive qui ne se limite plus aux définitions et peut être utilisée dès qu’il existe un « ensemble de termes et de valeurs »
    • HTML5 autorise un wrapper non sémantique <div> pour regrouper des <dt> et <dd> liés entre eux
    • Dans l’exemple sur les moteurs de navigateur, Chrome, Opera, Brave, Edge sont regroupés sous Blink-based browsers, tandis que Firefox, Tor, Librewolf le sont sous Gecko-based browsers
      <dl>
        <div class="dl-item">
          <dt>Chrome</dt>
          <dt>Opera</dt>
          <dt>Brave</dt>
          <dt>Edge</dt>
          <dd>Blink-based browsers</dd>
        </div>
        <div class="dl-item">
          <dt>Firefox</dt>
          <dt>Tor</dt>
          <dt>Librewolf</dt>
          <dd>Gecko-based browsers</dd>
        </div>
      </dl>
    
  • Métadonnées et débogage JSON

    • S’il s’agit d’une suite de faits accompagnés de leurs libellés, la liste descriptive convient bien à l’affichage de métadonnées
    • Un profil utilisateur peut aussi être représenté avec <dl> ; l’exemple exprime First Frank, Last Taylor, Age 44, Job Writer, Handle Paceaux sous forme de paires <dt> et <dd>
    • Une liste descriptive peut aussi servir au débogage JSON dans une application monopage
    • L’exemple DebugJson parcourt chaque paire key, value d’un objet via Object.entries(obj) et affiche la clé dans <dt><var>...</var></dt> et la valeur dans <dd><code>...</code></dd>
    • Si la valeur est un objet et non un tableau, DebugJson.createDl(value) est rappelé pour créer un <dl> imbriqué ; sinon, value.toString() est inséré dans <code>
      const debugJson = new DebugJson({foo: 'bar', arr: ['a', 'b'], car: 1}, '.container')
      debugJson.render();
    
    • Les listes descriptives conviennent très largement aux besoins en paires clé-valeur

Menus : <menu>

  • L’élément menu représente une liste de commandes et se rapproche davantage d’un web interactif que du simple rendu de contenu
  • menu convient à une liste de boutons d’outils, comme les contrôles de mise en forme d’un éditeur de texte enrichi
  • L’exemple d’éditeur de texte enrichi place les boutons Strong, Emphasize, Strike dans des li à l’intérieur d’un menu
  <menu>
    <li><button onclick="strong()">Strong</button></li>
    <li><button onclick="emphasize()">Emphasize</button></li>
    <li><button onclick="strike()">Strike</button></li>
  </menu>
  • D’après la spécification HTML, cela correspond à un usage de toolbar, et dans une page interactive, les groupes de boutons d’outils ont de fortes chances d’être des menu
  • L’exemple de contrôles vidéo relève aussi de menu, avec des button portant commandfor="vid-123" et command="--play", --mute, --fullscreen
  <div class="player player--video">
    <video source="whatever.mp4" id="vid-123"></video>
    <menu>
      <li><button commandfor="vid-123" command="--play">Play</button></li>
      <li><button commandfor="vid-123" command="--mute">Mute</button></li>
      <li><button commandfor="vid-123" command="--fullscreen">Fullscreen</button></li>
    </menu>
  </div>
  • Utiliser menu évite d’avoir à ajouter aria-role="menu" à une liste non ordonnée
  • Ne pas supposer que li ne va que dans deux conteneurs

    • Si l’on ne veut pas que les éléments de liste d’une navigation ressemblent à une liste classique, il faut appliquer le même traitement aux menu li
    • En haut de la feuille de style, on inclut donc non seulement nav li mais aussi menu li pour réinitialiser list-style-type, text-indent et margin
      nav li,
      menu li {
          list-style-type: none;
          text-indent: 0;
          margin: 0;
      }
    
  • <nav> et <menu> sont différents

    • nav n’est pas simplement un menu rempli de liens ; leur sens et leur contenu autorisé diffèrent
    • nav est un élément de section qui signifie qu’il fournit à l’utilisateur « plusieurs éléments concernant un déplacement vers un autre endroit »
    • nav peut contenir des paragraphes et des titres comme <p>, <h1-6>, ainsi que des listes comme <ul>, <ol>, <menu>
    • menu est un élément de liste qui signifie qu’il fournit à l’utilisateur « une liste de choses qu’il peut faire » et n’autorise que des éléments de liste <li>
    • menu et nav ne sont pas des choix mutuellement exclusifs ; menu peut se trouver dans nav, mais nav ne peut pas se trouver dans menu

Listes non ordonnées : <ul>

  • ul est la liste fourre-tout pour tous les besoins de liste qui ne sont couverts ni par les autres types de listes ni par nav
  • Dans les anciens HTML, la différence entre liste ordonnée et non ordonnée relevait surtout d’une distinction visuelle, comme des numéros contre des puces
  • Aujourd’hui, avec l’accessibilité, les lecteurs d’écran et le référencement, il faut se concentrer moins sur l’affichage visuel que sur le fait de savoir si l’ordre porte du sens
  • Une liste des membres d’un groupe de musique relève de ul, car l’ordre n’a pas d’importance
  <h3>Beatles</h3>
  <ul>
    <li>John Lennon</li>
    <li>Paul McCartney</li>
    <li>Ringo Star</li>
    <li>George Harrison</li>
  </ul>
  • Une liste de noms de groupes peut elle aussi être exprimée en liste non ordonnée
  <ul>
    <li>Beatles</li>
    <li>Rolling Stones</li>
    <li>Van Halen</li>
    <li>Foo Fighters</li>
  </ul>

1 commentaires

 
GN⁺ 1 시간 전
Commentaires sur Hacker News
  • Même en testant seulement les exemples, on dirait que datalist ne fonctionne pas bien dans Mobile Safari
    S’il y a des problèmes de compatibilité sur un marché aussi important, on peut presque dire qu’il n’existe en pratique que très peu de scénarios où cela vaut la peine de l’utiliser

    • C’est le genre d’information qui remet les pieds sur terre dont on n’a pas envie, mais dont on a besoin

      Il y a plus de dix ans, j’ai travaillé sur un projet qui utilisait un widget de suggestion de saisie assez agressif dans l’UI, et à l’époque on passait par un plugin jQuery
      C’était la partie la plus complexe du frontend, et en pratique la raison principale pour laquelle ce projet utilisait jQuery

      En lisant l’article, je me suis dit que réimplémenter ce frontend avec une version minimale et légère en JS serait un jeu d’enfant, mais la réalité est différente dès lors qu’on ne livre pas son propre environnement tel quel sur l’appareil de l’utilisateur
      Cela dit, les fonctionnalités incluses aujourd’hui dans la spécification HTML sont assez impressionnantes
      Depuis que j’ai lu XHTML au lycée, je n’ai presque pas suivi l’évolution de la spec, donc il faudrait sans doute que je jette parfois un œil à ce qui a changé
      Mais la compatibilité navigateur reste, aujourd’hui comme à l’époque, un vrai casse-tête

    • L’exemple de datalist fonctionne clairement sur mon iPhone
      Il s’intègre à la zone de suggestions d’autocomplétion au-dessus du clavier iOS natif
      En revanche, il n’y a aucun moyen de parcourir toutes les suggestions, mais ce n’est probablement pas non plus l’usage prévu de datalist

      Par contre, l’attribut disabled de group ne fonctionne clairement pas

    • Ça ne fonctionne pas non plus sur Firefox pour Android

    • Il y a longtemps, dans mon premier poste, datalist dans Firefox ne fonctionnait pas, et c’est pour ça que Firefox avait été retiré de la liste des navigateurs pris en charge

      C’est une fonctionnalité problématique depuis longtemps dès qu’on veut supporter autre chose que Chrome

    • Avec GBoard sur iOS, ça ne fonctionne pas bien

  • L’exemple qui ajoute l’attribut disabled à optgroup pour empêcher la sélection de certaines options semble cassé dans Mobile Safari
    En pratique, ce n’est pas désactivé, et on peut toujours sélectionner les éléments désactivés

    • Cela devrait fonctionner dans les versions récentes de Safari, donc ce n’est pas vraiment cassé, plutôt dans un état étrange

      https://caniuse.com/mdn-html_elements_optgroup_disabled

      Ça ressemble à un bug de Safari

    • C’est exactement pour ce genre de raison qu’il est difficile d’utiliser du HTML natif au-delà du strict minimum
      Même quand on a suffisamment lu et qu’on est assez sûr de soi pour écrire ce genre d’article, les commentaires finissent toujours par lister des comportements bizarres, des limitations et des absences de prise en charge selon les combinaisons navigateur/appareil

      Le div à outrance est peut-être un excès dans l’autre sens, mais au moins les comportements étranges et les limites sont assez cohérents et visibles
      Parce que cela s’imbrique de façon plus uniforme avec ce que j’ai écrit moi-même ou avec ce que le framework a généré

  • Article intéressant et complet

    Malheureusement, aujourd’hui beaucoup de développeurs passent directement à React sans apprendre HTML, et avec les LLM il est probable qu’ils ne l’apprennent plus du tout

    Du coup, même quand un simple HTML suffit, ils commencent par chercher un composant React

    • Je pense que ce n’est pas grave

      Quand j’ai dû utiliser XML pour la première fois, il fallait apprendre la spécification XML et produire le résultat à la main
      C’était avant l’existence de vraies bibliothèques de sérialisation
      J’ai ensuite vu les générations suivantes utiliser XML puis JSON comme format d’échange sans vraiment les apprendre à fond, et cela ne posait pas de problème particulier

      AJAX est passé du statut de technologie brûlante à celui d’acronyme dont plus personne ne connaît le sens, et aujourd’hui la plupart des gens ne reconnaissent même plus vraiment le terme
      AJAX n’est pas mort, il est juste devenu si banal qu’on n’a plus besoin d’un mot distinct pour en parler

    • Mon problème, c’est que j’ai appris HTML à fond il y a vingt ans, puis je n’ai découvert ses évolutions et améliorations qu’au hasard, petit à petit
      Pour le CSS, c’est encore plus vrai

    • Honnêtement, HTML est pénible

      Par exemple, l’approche HTML pour styler une partie d’un contrôle consiste à utiliser des pseudo-classes, mais selon les navigateurs les sélecteurs peuvent être différents
      On est alors obligé de tester navigateur par navigateur, puisqu’on ne peut pas savoir si cela fonctionne réellement correctement

      React est non seulement plus simple, mais aussi plus fiable
      Quand on le construit avec React et des div, on peut s’attendre à ce que cela fonctionne pareil dans tous les navigateurs

  • Bon contenu, mais il ne faut pas trop compter sur datalist
    En pratique, il manque de points d’intégration pour être vraiment utile, donc ce n’est pas adapté à grand-chose au-delà d’un petit prototype

    • J’ai utilisé datalist pour des suggestions d’autocomplétion et ça a très bien marché
    • Je crois avoir essayé autrefois de faire une combo box avec datalist, mais ça n’avait pas bien marché
  • Je me demande si un linter HTML aide vraiment à distinguer ce genre de différences
    J’aimerais aussi savoir s’il existe un linter capable d’imposer ce type de choix de balises sémantiques

    • L’idée même d’imposer des balises sémantiques ne me parle pas trop
      HTML est avant tout fait pour laisser de la liberté créative à l’auteur, et forcer une balise plutôt qu’une autre n’a pas vraiment de sens selon moi
      L’accessibilité est importante, mais il y a déjà assez de contraintes comme ça

    • La chose la plus proche que je connaisse est https://github.com/kristoff-it/superhtml#diagnostics

      SuperHTML vérifie non seulement la syntaxe, mais aussi l’imbrication des éléments et les valeurs d’attributs
      Il n’existe pas d’autre serveur de langage qui implémente en code de validation l’ensemble de la spécification HTML

  • Je l’ai appris aujourd’hui
    Je me demande pourquoi davantage de frameworks n’en tirent pas parti

    • Du point de vue de l’expérience utilisateur, c’est identique à une liste ordinaire
      On peut l’utiliser si cela aide à comprendre le code, mais dans l’arbre d’accessibilité du navigateur et dans tous les autres aspects, cela reste simplement une liste non ordonnée

      Pour indiquer qu’il s’agit d’une liste d’actions, il faut ajouter des attributs ARIA
      L’article mentionne role=menu, mais cela ne suffit pas à lui seul : chaque élément doit aussi avoir le rôle menuitem
      Le WAI Authoring Practices Guide explique les rôles et les attentes en matière d’interaction, mais il ne faut pas copier les exemples de code tels quels, et il ne faut surtout pas utiliser ce rôle pour des menus de navigation

      https://www.w3.org/WAI/ARIA/apg/patterns/menubar/

    • Les gens intelligents n’apprennent pas le HTML compliqué et règlent le problème avec plusieurs div

    • Le HTML moderne a plein de fonctionnalités intéressantes

      J’aime demander aux gens ce qu’ils pensent qu’un élément fait
      Moi non plus, au début, je n’en devinais aucune correctement

  • Même après plusieurs années comme lead frontend, j’y ai trouvé beaucoup d’informations utiles que je ne connaissais pas
    Je pense qu’on va clairement commencer à en essayer certaines dans l’entreprise aussi

  • Ce serait bien si les designers aimaient simplement l’apparence par défaut de datalist

    • D’après mon expérience, le manque de personnalisation du style est le principal obstacle à l’utilisation des fonctionnalités HTML natives
  • Le billet de blog est vraiment très bien, mais je n’arrive pas à trouver un moyen de voir d’un coup la liste complète de tous les articles du blog

    https://blog.frankmtaylor.com/archive ne marche pas

    https://blog.frankmtaylor.com/archives non plus

    https://blog.frankmtaylor.com/posts ne marche pas non plus

    https://blog.frankmtaylor.com/all n’existe pas non plus

    https://blog.frankmtaylor.com/blog non plus

    Comme beaucoup de gens ont plus de 10�a0000 favoris, ce serait vraiment pratique d’avoir une page de liste unique qui énumère tout ce qui a été publié jusqu’ici, sans description ni texte complet

    • Tu veux sans doute parler d’un plan du site
      La plupart des blogs ont un sitemap.xml qui liste tous les articles

      Et je me demande aussi pourquoi tu voudrais parcourir les 235 articles en entier