Saltar al contenido principal
Sábado 14 de marzo - Trucos y buenas prácticas para auditar accesibilidad en Figma¡Apúntate ya!
Volver a la página del blog

Cuando HTML se queda corto: roles de ARIA

Tiempo de lectura: 6 minutos
Autor
Mía Salazar
Fecha de publicación
05 / 03 / 2026

En accesibilidad web repetimos mucho una idea: primero HTML semántico. Y es correcta. Un <button> siempre será mejor que un <div> con onclick. Un <nav> siempre mejor que un contenedor genérico con enlaces.

Pero hay un punto en el que HTML deja de describir correctamente lo que está ocurriendo. No porque esté mal diseñado, sino porque la web moderna construye patrones de interacción que no existen como elementos nativos. Cuando eso ocurre, los productos de apoyo se enfrentan a un conjunto de cajas sin relación lógica entre ellas.

Ahí es donde ARIA tiene sentido: no como sustituto de HTML, sino como una capa que describe comportamientos, relaciones y estados que el marcado por sí solo no puede expresar.

Importante: ARIA solo informa a la tecnología de asistencia sobre qué es un elemento. ARIA no añade funcionalidad de teclado. Si usas un rol de listbox o tree, debes programar mediante JavaScript la gestión del foco y los eventos de teclado (flechas, Esc, Enter) para que el componente sea realmente usable.

El problema real: la semántica de la interacción

HTML describe bien documentos. Encabezados, párrafos, listas, formularios… todo eso funciona perfectamente con tecnologías de asistencia. El problema aparece cuando dejamos de construir documentos y empezamos a construir interfaces.

Una pestaña que cambia contenido, un selector con autocompletado…. Visualmente es evidente lo que pasa. Pero para un producto de apoyo  no lo es.

Tabs: tablist, tab y tabpanel

Las pestañas son probablemente el mejor ejemplo de algo que HTML no puede representar por sí solo. No existe <tabs> en HTML.

Si hacemos esto:

<div class="tabs">
  <button>Perfil</button>
  <button>Seguridad</button>
  <button>Facturación</button>
</div>
<div>Contenido de la sección seleccionada</div>

Lenguaje del código:HTML

Para un lector de pantalla son solo tres botones y un bloque de texto sin relación entre sí, jamás entenderemos la relación entre estos botones y cuál de ellos está seleccionado.

Con ARIA podemos describir la relación:

<div role="tablist" aria-label="Configuración de cuenta">
  <button role="tab" id="tab-profile" aria-selected="true">
    Perfil
  </button>
  <button
    role="tab"
    id="tab-security"
    aria-selected="false">
    Seguridad
  </button>
  <button role="tab" id="tab-billing" aria-selected="false">
    Facturación
  </button>
</div>
<section
  id="panel-profile"
  role="tabpanel"
  aria-labelledby="tab-profile">
  Datos personales…
</section>

Lenguaje del código:HTML

Ahora la tecnología de asistencia entiende que existe un número concreto de pestañas, que una de ellas está seleccionada y que están relacionadas. No es decoración. Es información estructural.

Barras de desplazamiento personalizadas: scrollbar

Si por diseño decides no usar el scroll nativo del navegador, debes informar al sistema de que ese elemento actúa como una barra de desplazamiento.

<div class="custom-scroll-track">
  <div
    role="scrollbar"
    aria-orientation="vertical"
    aria-valuemin="0"
    aria-valuemax="100"
    aria-valuenow="25"></div>
</div>

Lenguaje del código:HTML

Diálogos personalizados: dialog

HTML5 introdujo el elemento <dialog>, pero muchos proyectos siguen utilizando modales completamente personalizados construidos con <div> y JavaScript.

Si hacemos esto:

<div class="modal">
  <h1>Confirmar eliminación</h1>
  <p>Esta acción no se puede deshacer.</p>
  <button>Cancelar</button>
  <button>Eliminar</button>
</div>

Lenguaje del código:HTML

Para un lector de pantalla esto es simplemente contenido más en el flujo del documento. Con ARIA podemos comunicar que se trata de una ventana de diálogo independiente:

<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="dialog-title">
  <h2 id="dialog-title">Confirmar eliminación</h2>
  <p>Esta acción no se puede deshacer.</p>
  <button>Cancelar</button>
  <button>Eliminar</button>
</div>

Lenguaje del código:HTML

Aquí ARIA expresa algo que HTML genérico no puede: que el usuario ha entrado en una región interactiva aislada del resto de la página.

Árboles de datos: tree

El rol tree permite a los usuarios de lectores de pantalla navegar por estructuras jerárquicas (como un explorador de archivos) sabiendo qué nodos están expandidos o colapsados.

<ul role="tree" aria-label="Explorador de archivos">
  <li role="treeitem" aria-expanded="true">
    <span>Documentos</span>
    <ul role="group">
      <li role="treeitem">Factura_enero.pdf</li>
      <li role="treeitem">CV_final.docx</li>
    </ul>
  </li>
  <li role="treeitem" aria-expanded="false">Imágenes</li>
</ul>

Lenguaje del código:HTML

Actualizaciones dinámicas: status y alert

Hay información que aparece sin recargar la página: formularios, validaciones, notificaciones. Visualmente es obvio. Para accesibilidad no lo es.

Usando role="status" avisaremos al producto de apoyo, sin interrumpir a la persona usuaria, de las notificaciones o de la información que aparezca en pantalla

<div role="status">Guardado correctamente</div>

Lenguaje del código:HTML

O si necesitamos explícitamente interrumpir a la persona ya que es un asunto urgente, tenemos role=”alert”

<div role="alert">La sesión va a expirar</div>

Lenguaje del código:HTML

Estos roles hacen que el lector de pantalla anuncie el cambio automáticamente.

Combobox y Listbox: Selección avanzada

Cuando un <select> nativo se queda corto (por ejemplo, porque necesitas filtrar una lista de cientos de países o usuarios), recurrimos a este patrón. Se divide en dos piezas clave:

  • role="combobox": Es el "director de orquesta". Normalmente se aplica al contenedor o al campo de entrada (input). Su función es avisar al usuario de que ese campo no es un simple texto, sino que controla la aparición de una lista de opciones.
  • role="listbox": Es el contenedor de los resultados. Mientras que un estándar solo indica una lista de elementos, un listbox indica una lista de opciones seleccionables. Cada elemento hijo debe llevar el role="option".
<div
  role="combobox"
  aria-expanded="true"
  aria-haspopup="listbox">
  <input
    type="text"
    aria-autocomplete="list"
    aria-activedescendant="opt-1" />

  <ul id="results-list" role="listbox">
    <li id="opt-1" role="option" aria-selected="true">
      Madrid
    </li>
    <li id="opt-2" role="option">Málaga</li>
  </ul>
</div>

Lenguaje del código:HTML

Grid interactivo: grid

Las tablas HTML funcionan muy bien para datos estáticos, pero una tabla editable con navegación por celdas es un patrón distinto.

<div role="grid" aria-label="Inventario">
  <div role="row">
    <span role="columnheader">Producto</span>
    <span role="columnheader">Stock</span>
  </div>
  <div role="row">
    <span role="gridcell">Teclado</span>
    <span role="gridcell">23</span>
  </div>
</div>

Lenguaje del código:HTML

Este rol comunica que el usuario puede navegar celda a celda como en una hoja de cálculo, algo que una tabla semántica tradicional no cubre en interfaces altamente interactivas.

Slider personalizado: slider

Si usas <input type="range">, ya es accesible. El problema aparece cuando el diseño exige un control completamente custom. 

<div
  role="slider"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-valuenow="40"
  aria-label="Volumen"></div>

Lenguaje del código:HTML

Ahora el lector de pantalla puede anunciar el valor actual y el usuario puede modificarlo con teclado

Esta situación es más común de lo que nos gustaría, y suele suceder cuando deseamos crear diferentes tipos de elementos de formulario (inputs, selects, textareas) y no podemos utilizar las etiquetas nativas porque deseamos un comportamiento un poco distinto.

Toolbar: agrupación de controles

Cuando tienes varios botones que están relacionados entre sí (como los controles de un editor de texto o los filtros de una tabla), HTML no expresa esa relación. Para un lector de pantalla, son solo botones sueltos en el flujo de la página.

El rol toolbar agrupa estos elementos en un solo contenedor lógico. Esto permite que el usuario entienda que no son botones aislados, sino herramientas de un mismo grupo funcional.

<div role="toolbar" aria-label="Formato de texto">
  <button type="button" aria-pressed="false">
    Negrita
  </button>
  <button type="button" aria-pressed="false">
    Cursiva
  </button>
  <button type="button" aria-pressed="false">
    Subrayado
  </button>
</div>

Lenguaje del código:HTML

El usuario entiende que no son botones aislados, sino herramientas de un mismo grupo.

Cuándo no usar ARIA

Hay una regla sencilla:

Si existe un elemento HTML nativo que hace lo mismo, úsalo.

Malos ejemplos:

<div role="button">Enviar</div>
<span role="link">Inicio</span>

Lenguaje del código:HTML

Un <button> y un <a> ya resuelven el problema mejor que cualquier ARIA.

ARIA no arregla una mala elección de HTML. Solo describe comportamientos que HTML no puede describir.

Conclusión

ARIA no es para "hacer accesible" una página. Es para hacer comprensible una interfaz interactiva cuando HTML deja de ser suficiente.

Los roles como tab, switch, combobox, slider o status existen porque la web ya no es solo un documento: es una aplicación. Y cuando construimos aplicaciones, necesitamos comunicar estados, relaciones y expectativas de interacción a quienes no ven la pantalla.

La accesibilidad no consiste en añadir atributos, sino en transmitir significado. Y ARIA, bien usado, es exactamente eso: significado donde antes solo había comportamiento.

Escrito por:

  • Mía Salazar

    Front-end developer especializada en accesibilidad web, con experiencia en Angular, React y Vue. Mentora en Step4ward y TechSHEssions, escribe sobre desarrollo web y ha participado como speaker en numerosos foros.Visita su perfil de LinkedIn

Únete a nuestra comunidad para aprender y estar al día sobre accesibilidad digital.

Recibirás recursos y artículos semanalmente para que puedas aprender, compartir y ser parte de la comunidad de accesibilidad digital.
¿Quieres colaborar en nuestra Newsletter? Escríbenos a hola@weaaare.com