Normativas · ARIA

Rol Control compuesto

listbox

Marca un elemento como una lista de opciones seleccionables. Se recomienda usar <select> para el caso simple de selección única. Recurrir a role="listbox" cuando se necesite estilo personalizado, selección múltiple con renderizado propio o combinación con un combobox.

Cuándo utilizarlo

Se debe usar <select> (selección única) o <select multiple> siempre que sea posible. El elemento nativo proporciona el modelo de interacción completo, incluido el manejo de teclado correcto para cada plataforma.

role="listbox" es adecuado cuando:

  • El listbox es el desplegable de un combobox personalizado.
  • Se necesita contenido enriquecido en las opciones (iconos, texto secundario) que <select> no puede renderizar.
  • Se requiere selección múltiple con estilo de marca de verificación personalizado.
  • Se está construyendo un transfer list o un selector filtrable.

Los elementos hijo deben tener role="option" (con role="group" permitido como contenedor intermedio para la organización en secciones). Se debe establecer aria-multiselectable="true" en los listboxes de selección múltiple.

Contrato de teclado y foco

Según el patrón de listbox de la APG:

  • Tab mueve el foco al listbox; Tab lo saca. Dentro del listbox, el foco permanece en el contenedor y la opción «activa» se rastrea mediante aria-activedescendant.
  • Las flechas Arriba/Abajo mueven la opción activa.
  • Inicio / Fin saltan a la primera / última opción.
  • Selección única: cada pulsación de flecha también selecciona la opción activa.
  • Selección múltiple: Espacio alterna la selección de la opción activa; Shift+Flecha extiende un rango contiguo; Ctrl/Cmd+A selecciona todo.
  • Escritura anticipada: al escribir una letra, el cursor salta a la siguiente opción que comienza con esa letra.

Errores frecuentes

  • Mover el foco del DOM a cada opción en lugar de usar aria-activedescendant. Rompe la escritura anticipada y la integración con el combobox.
  • Elementos hijo role="option" sin atributos idaria-activedescendant no puede referenciarlos.
  • Listbox de selección múltiple sin aria-multiselectable="true". Los lectores de pantalla lo anuncian como de selección única.
  • El listbox contiene opciones situadas en otra parte del DOM sin usar aria-owns para hacer explícita la relación.
  • Usar role="listbox" para una lista estática de elementos de solo lectura. En ese caso corresponde role="list", no listbox — listbox implica interactividad.

Ejemplo

<label id="topicsLabel">Seleccione sus temas</label>
<ul
  role="listbox"
  aria-labelledby="topicsLabel"
  aria-multiselectable="true"
  tabindex="0"
  aria-activedescendant="topic-1"
>
  <li id="topic-1" role="option" aria-selected="true">Accesibilidad</li>
  <li id="topic-2" role="option" aria-selected="false">Tecnología de apoyo</li>
  <li id="topic-3" role="option" aria-selected="true">Estándares</li>
</ul>