1 puntos por GN⁺ 1 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Las listas de HTML deben elegirse por su significado y forma de interacción, no por su apariencia visual, y se dividen en listas de control, ordenadas, descriptivas, de menú y desordenadas
  • Para opciones fijas, lo correcto es usar <select>/<option>; para entradas con sugerencias, <datalist>, y hay que distinguir cómo funcionan multiple, optgroup, size y value
  • <ol> se usa para procedimientos, eventos o continuos cuyo significado cambia si se altera el orden, y reversed solo invierte la numeración, no el orden real de los elementos
  • <dl> en HTML5 se amplió más allá de las listas de definiciones y ahora sirve como lista descriptiva, adecuada para pares clave-valor, metadatos y depuración de JSON
  • <menu> se usa para listas de comandos como botones de herramientas; su significado y contenido permitido difieren de nav, y las demás listas generales quedan a cargo de <ul>

Listas de control: <select>/<option> y <datalist>

  • También se pueden construir listas interactivas para el usuario dentro de formularios
  • Las opciones fijas van con <select> y <option>

    • Si el usuario debe poder elegir solo entre los elementos de la lista, se usan <select> y <option>
    • El ejemplo de lista de idiomas coloca opciones como Select a Language, English, French, Spanish, Portuguese dentro de <select name="languages">
    • Un <select> básico permite elegir exactamente una sola opción
    • Para permitir seleccionar varios elementos, se agrega el atributo multiple
      • Al usar multiple, cambia la presentación de la lista, se muestran todas las opciones y el usuario puede elegir varias con Shift o Cmd + clic
      • Si se usan select y option reales, la semántica nativa del navegador se encarga de todo, sin necesidad de agregar manualmente aria-multiselectable a un elemento de lista con role="listbox"
  • Agrupar opciones relacionadas con <optgroup>

    • Si quieres agrupar idiomas por familia lingüística, puedes agrupar la lista de opciones con <optgroup>
    • El ejemplo crea <optgroup> con label como Germanic, Romance, Celtic, y coloca dentro English, French, Spanish, Portuguese, Irish, Welsh
    • Si quieres impedir la selección de un subgrupo específico, agrega el atributo disabled a ese <optgroup>
    • En el ejemplo, se agrega disabled al grupo Celtic para desactivar el conjunto que incluye Irish y Welsh
  • Mejorar con funciones nativas de HTML

    • Si necesitas una separación visual entre grupos, puedes usar <hr> dentro de <select>, donde está permitido
    • El atributo size controla cuántos elementos se muestran a la vez, así que es útil para listas largas
    • Si usas size junto con optgroup, las etiquetas de grupo también ocupan espacio de visualización
    • El ejemplo usa <select name="languages" size="4" multiple> con grupos Germanic, Romance, Celtic, Afroasiatic, separadores <hr /> entre ellos, e incluye también Hebrew y Arabic

Lista de sugerencias: <datalist>

  • Si no quieres que el usuario elija obligatoriamente solo de la lista, sino que esta sugiera opciones, se usa <datalist>
  • <datalist> se conecta en dos pasos
    • Se crea un <datalist> y se le asigna un id
    • Ese valor de id se coloca en el atributo list del <input> correspondiente
  • El ejemplo de sugerencias de idiomas pone opciones como English, French, Spanish, Portuguese, Irish, Welsh, Hebrew, Arabic dentro de <datalist id="languages">, y lo conecta al campo de entrada con <input name="language" list="languages">
  • Cómo funciona <option value>

    • El valor por defecto de <option> es el texto que envuelve, y si existe el atributo value, ese valor sobrescribe el predeterminado mientras el texto actúa como etiqueta
    • En <select>, esto no suele ser un gran problema porque el usuario solo ve el texto, pero en <datalist> puede causar confusión porque el usuario ve la etiqueta, la elige y luego en el campo aparece el value
    • En el ejemplo, si se selecciona <option value="cy">Welsh</option>, el usuario ve Welsh, pero en el campo se inserta cy
    • Al usar <datalist>, hay que asumir que el valor insertado no es la etiqueta, sino value
  • Combinación con varios tipos de entrada

    • <datalist> no sirve solo para opciones de texto; también puede usarse con otros tipos de input
    • El ejemplo de selección por semana conecta <datalist id="preferred-weeks"> con <input type="week" name="week" id="camp-week" min="2026-W2" max="2026-W51" list="preferred-weeks" />
    • Las semanas sugeridas son 2026-W22, 2026-W23, 2026-W24, 2026-W25
  • Combinación con <input type="range">

    • <datalist> no se limita a valores de cadena; también funciona con números, por lo que puede combinarse con una entrada de rango para crear puntos etiquetados sobre el rango
    • El ejemplo de porcentaje de propina conecta <datalist id="recommended-tips"> con <input type="range" name="tips" id="tips" min="0" max="50" step="1" list="recommended-tips" /> y añade etiquetas 10%, 18%, 30%, 45%
    • En navegadores basados en Chrome, se usa @supports (x: attr(x type(percentage))) para leer el valor de label con attr(), declarar el valor como porcentaje con type() y luego posicionar las opciones con position: absolute
    • El enfoque para Firefox usa @supports not (x: attr(x type(percentage))), y el valor se muestra con ::before
    • Este enfoque no garantiza que todos los navegadores funcionen igual ni que se muestre de forma idéntica en pantalla

Lista ordenada: <ol>

  • Para un conjunto de elementos que deben leerse en un orden específico, se usa <ol>
  • El criterio no es si deben verse números al lado de los elementos, sino si el significado de la lista cambia cuando se altera el orden
  • Las colecciones adecuadas para <ol> incluyen algoritmos, secuencias de eventos, elementos sobre un continuo creciente o decreciente, recetas y listas en orden alfabético
  • El ejemplo de receta de pan de plátano expresa con <ol> la secuencia de precalentar el horno y engrasar el molde, mezclar ingredientes, verter la mezcla, hornear 60 minutos o hasta que un palillo salga limpio, y dejar enfriar sobre una rejilla
  • Una lista de ingredientes en orden alfabético también corresponde a <ol>, porque sigue el continuo del alfabeto, y se ordena como baking soda, bananas, brown sugar, butter, eggs, flour, salt
  • Anidar listas ordenadas y desordenadas

    • Una lista ordenada bien estructurada debe permitir entender qué ocurre y en qué orden incluso sin ver cómo la renderiza el navegador
    • En el ejemplo de la receta, se usa <ol> para los pasos principales y, dentro de cada paso, <ul> para elementos cuyo orden no importa, y nuevamente <ol> para subpasos donde el orden sí importa
    • La estructura mantiene el orden superior de Prepare, Mix, Pour, Bake, Cool, mientras que los elementos paralelos dentro de Prepare y Bake se expresan con <ul>, y los procedimientos dentro de Mix y Cool con <ol>
  • reversed

    • El atributo reversed cambia la numeración de ascendente a descendente
    • No cambia el orden real de los elementos de la lista
    • Puede usarse en una lista de ingredientes y cantidades mostrada de most to least, es decir, de mayor a menor
    • El ejemplo coloca en <ol reversed> los elementos eggs (2), flour (2 cups), bananas (2) (mashed), brown sugar (¾ cup), butter (½ cup), baking soda (1 teaspoon), salt (¼ teaspoon)
  • Invertir el orden real de los elementos con JavaScript

    • Si quieres invertir realmente la lista, puedes reordenar en JavaScript los hijos li en sentido inverso y alternar el atributo reversed
    • La función de ejemplo convierte el resultado de list.querySelectorAll('li') en un arreglo, aplica .reverse(), luego vacía con list.innerHTML = '' y vuelve a insertar con list.append(...children)
    • Al final llama a list.toggleAttribute('reversed')
    • El evento de ejemplo ejecuta la inversión al hacer doble clic con orderedList.addEventListener('dblclick', (evt) => { reverseList(orderedList) })
  • start

    • El atributo start sirve para mantener la continuidad de la numeración cuando se divide una sola lista enorme en varias listas ordenadas
    • En el ejemplo de la receta de banana bread, Prepare se deja como ul, Mix usa <ol start=2>, Pour usa <ol start=5>, y Cool usa <ol start=7> para conservar la secuencia de pasos entre listas
    • Aunque haya una sección intermedia expresada como lista no ordenada, como 6: Bake, luego se puede iniciar el ol de Cool en start=7 para mantener el flujo numérico del procedimiento completo

Lista descriptiva: <dl>, <dt>, <dd>

  • Una lista descriptiva (description list) es un tipo de lista que evita forzar todo el contenido dentro de ol o ul
  • Lista de definiciones en HTML 4

    • En HTML 4 no se llamaba description list, sino lista de definiciones (definition list), y estaba orientada a un uso más limitado de proporcionar definiciones
    • La estructura se componía del término a definir en <dt> y el contenido de la definición en <dd>; para un uso semánticamente preciso, el término definido se envolvía en <dfn>
    • El ejemplo conecta throw y yeet con una misma definición, y asigna definiciones por separado a no cap y 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>
    
  • Significado ampliado en HTML5

    • En HTML5 dejó de limitarse a definiciones y pasó a ser una lista descriptiva que puede usarse cuando hay un “conjunto de términos y valores”
    • En HTML5 se permite un envoltorio no semántico <div> para agrupar <dt> y <dd> relacionados
    • En el ejemplo de motores de navegador, Chrome, Opera, Brave, Edge se agrupan bajo Blink-based browsers, y Firefox, Tor, Librewolf bajo 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>
    
  • Metadatos y depuración de JSON

    • Si tienes una secuencia de hechos y etiquetas, una lista descriptiva es adecuada para mostrar metadatos
    • Un perfil de usuario también puede ir en <dl>; el ejemplo expresa First Frank, Last Taylor, Age 44, Job Writer, Handle Paceaux como pares <dt> y <dd>
    • En aplicaciones de una sola página también puede usarse una lista descriptiva para depuración de JSON
    • El ejemplo DebugJson recorre cada key, value del objeto con Object.entries(obj) y renderiza la clave como <dt><var>...</var></dt> y el valor como <dd><code>...</code></dd>
    • Si el valor es un objeto y no un arreglo, vuelve a llamar a DebugJson.createDl(value) para crear un <dl> anidado; en cualquier otro caso, coloca value.toString() dentro de <code>
      const debugJson = new DebugJson({foo: 'bar', arr: ['a', 'b'], car: 1}, '.container')
      debugJson.render();
    
    • La lista descriptiva se adapta ampliamente al requisito de pares clave-valor

Menú: <menu>

  • El elemento menu representa una lista de comandos y está más cerca de la web interactiva que de la simple renderización de contenido
  • menu encaja para una lista de botones de “herramientas”, como los controles de edición de texto en un editor de texto enriquecido
  • El ejemplo del editor de texto enriquecido coloca los botones Strong, Emphasize, Strike como li dentro de 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>
  • Según la especificación de HTML, esto corresponde al uso de una barra de herramientas (toolbar), y en una página interactiva, donde haya botones de herramientas, es muy probable que correspondan a menu
  • El ejemplo de controles de video también va en menu, con button que usan commandfor="vid-123" y 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>
  • Al usar menu, no hace falta agregar aria-role="menu" a una lista desordenada
  • No asumir que li solo entra en dos contenedores

    • Si no quieres que los elementos de una lista de navegación se vean como una lista común, hay que aplicar el mismo tratamiento también a menu li
    • En la parte superior de la hoja de estilos, además de nav li, se incluye menu li para reiniciar list-style-type, text-indent y margin
      nav li,
      menu li {
          list-style-type: none;
          text-indent: 0;
          margin: 0;
      }
    
  • <nav> y <menu> no son lo mismo

    • nav no es simplemente un menu con enlaces; su significado y su contenido permitido son distintos
    • nav es un elemento de sección cuyo significado es ofrecer al usuario “varios elementos relacionados con ir a algún lugar”
    • nav puede incluir párrafos y encabezados como <p>, <h1-6>, así como listas como <ul>, <ol>, <menu>
    • menu es un elemento de lista cuyo significado es ofrecer al usuario “una lista de cosas que puede hacer”, y solo permite elementos <li>
    • menu y nav no son opciones mutuamente excluyentes: menu puede ir dentro de nav, pero nav no puede ir dentro de menu

Lista desordenada: <ul>

  • ul es la lista comodín para las necesidades de listado que no resuelven otros tipos de lista ni nav
  • En el HTML antiguo, la diferencia entre lista ordenada y desordenada se parecía más a una diferencia visual, como números frente a viñetas
  • Hoy se consideran accesibilidad, lectores de pantalla y optimización para motores de búsqueda, así que hay que enfocarse menos en la apariencia visual y más en si el orden tiene significado
  • La lista de integrantes de una banda no depende del orden, así que corresponde usar ul
  <h3>Beatles</h3>
  <ul>
    <li>John Lennon</li>
    <li>Paul McCartney</li>
    <li>Ringo Star</li>
    <li>George Harrison</li>
  </ul>
  • Una lista de nombres de bandas también puede expresarse como lista desordenada
  <ul>
    <li>Beatles</li>
    <li>Rolling Stones</li>
    <li>Van Halen</li>
    <li>Foo Fighters</li>
  </ul>

1 comentarios

 
GN⁺ 1 시간 전
Comentarios de Hacker News
  • Con solo probar los ejemplos, parece que datalist no funciona bien en Mobile Safari
    Si hay problemas de compatibilidad en un mercado tan grande, podría decirse que en la práctica casi no hay escenarios en los que valga la pena usarlo

    • Es el tipo de balde de agua fría de la realidad que no quería, pero sí necesitaba

      Hace más de 10 años trabajé en un proyecto que usaba un widget de sugerencias de entrada bastante agresivo en la UI, y en ese entonces usamos un plugin de jQuery
      Era la parte más compleja del frontend y, en la práctica, la razón principal por la que usábamos jQuery en ese proyecto

      Al leer el artículo pensé que sería facilísimo volver a implementar ese frontend con una versión mínima y ligera en JS, pero la realidad no es así a menos que puedas entregarles a los usuarios exactamente tu mismo entorno en sus dispositivos
      Aun así, las funciones que hoy están incluidas en la especificación de HTML son bastante impresionantes
      Desde que leí XHTML en la preparatoria casi no he seguido los cambios de la especificación, así que de vez en cuando debería revisar qué ha cambiado
      Pero la compatibilidad entre navegadores sigue siendo un dolor de cabeza, tanto antes como ahora

    • El ejemplo de datalist definitivamente funciona en mi iPhone
      Se integra en el área de sugerencias de autocompletado encima del teclado nativo de iOS
      Eso sí, no hay manera de recorrer todas las sugerencias, y probablemente tampoco era esa la forma prevista de usar datalist

      Pero el atributo disabled de group definitivamente no funciona

    • Tampoco funciona en Firefox para Android

    • Hace mucho tiempo, en mi primer trabajo, datalist en Firefox no funcionaba, y por eso Firefox quedó fuera de la lista de navegadores compatibles

      Si quieres dar soporte a navegadores que no sean Chrome, esta función ha sido problemática desde hace mucho tiempo

    • Con GBoard en iOS no funciona bien

  • El ejemplo que agrega el atributo disabled a optgroup para impedir seleccionar algunas opciones parece estar roto en Mobile Safari
    En realidad no se desactiva y los elementos deshabilitados siguen pudiéndose seleccionar

    • Debería funcionar en Safari reciente, así que no diría que está roto, más bien está en un estado extraño

      https://caniuse.com/mdn-html_elements_optgroup_disabled

      Parece posible que sea un bug de Safari

    • Aquí se ve por qué es difícil usar HTML nativo para algo más que lo básico
      Aunque leas bastante y sepas lo suficiente como para escribir un artículo así con confianza, en los comentarios siempre terminan apareciendo comportamientos raros, limitaciones y faltas de soporte según cada combinación de navegador y dispositivo

      El exceso de div puede ser una elección que se fue demasiado al otro extremo, pero al menos sus rarezas y límites suelen ser bastante consistentes y visibles
      Porque encajan de manera más uniforme con lo que yo mismo escribí o con lo que generó el framework

  • Es un artículo interesante y bastante completo

    Por desgracia, hoy hay muchos desarrolladores que no aprenden HTML y entran directo a React, y ahora con los LLM es aún más probable que no lleguen a aprender HTML en absoluto

    Por eso terminan buscando primero un componente de React incluso en lugares donde HTML simple sería suficiente

    • Aun así, me parece bien

      Cuando tuve que usar XML por primera vez, había que aprender la especificación de XML y generarlo a mano
      Era una época en la que prácticamente no existían librerías de serialización
      Después vi a generaciones más jóvenes usar XML y luego JSON como formatos de intercambio sin aprenderlos por completo, y no pasó nada grave

      AJAX también pasó de ser una tecnología nueva y emocionante a una etapa donde la gente ya ni sabía qué significaban sus siglas, y ahora la mayoría ni siquiera reconoce bien el término
      AJAX no murió; simplemente se volvió tan común que ya no hacía falta una palabra aparte para describirlo

    • Mi problema es que aprendí HTML a fondo hace 20 años y desde entonces solo me he ido enterando por casualidad, poco a poco, de cómo ha cambiado y mejorado
      Con CSS me pasa aún más

    • Si soy honesto, HTML es engorroso

      Por ejemplo, el enfoque “a lo HTML” para estilizar partes de un control consiste en usar pseudoclases, pero a veces los selectores cambian según el navegador
      Entonces tienes que probar por navegador porque no sabes si realmente va a funcionar bien

      React no solo es más fácil, también es más confiable
      Si lo construyes con React y div, puedes esperar que se comporte igual en todos los navegadores

  • Buen contenido, pero no conviene esperar demasiado de datalist
    En realidad le faltan puntos de integración para que sea útil de verdad, así que no sirve para mucho más que prototipos pequeños

    • He usado datalist para sugerencias de autocompletado y me funcionó muy bien
    • Creo que alguna vez intenté hacer un combobox con datalist, pero no salió bien
  • Me pregunto si un linter de HTML realmente ayuda a distinguir este tipo de diferencias
    También me gustaría saber si existe algún linter que pueda hacer cumplir este tipo de elección de etiquetas semánticas

    • No me termina de convencer eso de “hacer cumplir” etiquetas semánticas
      HTML está hecho, ante todo, para que quien lo escribe lo use de forma creativa, y no me parece que tenga sentido forzar unas etiquetas sobre otras
      La accesibilidad es importante, pero ya hay suficientes restricciones

    • Lo más cercano que conozco es https://github.com/kristoff-it/superhtml#diagnostics

      SuperHTML valida no solo la sintaxis, sino también el anidamiento de elementos y los valores de atributos
      No hay otro language server que implemente en código de validación toda la especificación de HTML

  • Hoy aprendí algo nuevo
    Me pregunto por qué más frameworks no aprovechan esto

    • Desde la perspectiva de la experiencia de usuario, es lo mismo que una lista común
      Puedes usarlo si ayuda a entender el código, pero en el árbol de accesibilidad del navegador y en todo lo demás no deja de ser una lista desordenada

      Si quieres comunicar que algo es una lista de acciones, tienes que agregar atributos ARIA
      El artículo menciona role=menu, pero eso solo no basta; cada elemento también necesita el rol menuitem
      La WAI Authoring Practices Guide explica los roles y las expectativas de interacción, pero no copies los ejemplos de código tal cual, y en particular no uses ese rol para menús de navegación

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

    • La gente lista resuelve eso con varios div en lugar de aprender HTML complicado

    • Hoy en día HTML tiene funciones interesantes

      Me gusta preguntarle a la gente qué creen que hace cierto elemento
      Yo tampoco le atiné para nada la primera vez

  • Incluso después de haber trabajado varios años como líder de frontend, aquí había mucha información útil que no conocía
    En la empresa seguramente empezaremos a probarlo de verdad

  • Ojalá a los diseñadores les gustara la apariencia predeterminada de datalist

    • En mi experiencia, la falta de personalización de estilos es el mayor obstáculo para usar funciones nativas de HTML
  • El post del blog está muy bueno, pero no logro encontrar una forma de ver de una sola vez la lista de todos los artículos del blog

    https://blog.frankmtaylor.com/archive no funciona

    https://blog.frankmtaylor.com/archives tampoco

    https://blog.frankmtaylor.com/posts no sirve

    https://blog.frankmtaylor.com/all no existe

    https://blog.frankmtaylor.com/blog tampoco

    Como hay mucha gente con más de 10 mil marcadores, sería realmente práctico tener una única página de lista que enumere todo lo que ha escrito hasta ahora, sin explicaciones ni el texto completo de cada artículo

    • Creo que te refieres a un sitemap
      La mayoría de los blogs tienen un sitemap.xml con todos los artículos listados

      Y también me da curiosidad por qué querrías revisar los 235 posts completos de principio a fin