ARIA roles, states y properties
ARIA (Accessible Rich Internet Applications) es un conjunto de atributos que puedes agregar al HTML para proporcionar información adicional a las tecnologías asistivas. Se usa cuando el HTML semántico no es suficiente para comunicar el significado o estado de un componente interactivo.
La regla de oro de ARIA
- Primera regla de ARIA: NO uses ARIA si puedes usar un elemento HTML nativo que ya tiene la semántica
- <button> es SIEMPRE mejor que <div role='button'> — el nativo viene con focus y keyboard handling gratis
- ARIA no cambia el comportamiento — solo cambia lo que el lector de pantalla anuncia al usuario
- Si agregás role='button' a un div, también debes agregar tabindex='0' y manejar Enter y Space con JavaScript
- ARIA mal usado es PEOR que no usar ARIA — puede confundir al lector de pantalla y al usuario
Tabla de ARIA roles, states y properties
Usá esta tabla para decidir si necesitás ARIA o si el HTML semántico ya resuelve el problema.
| Tipo | Qué comunica | Ejemplos | Cuándo usarlo |
|---|---|---|---|
| ARIA roles | Tipo de elemento o patrón de interfaz. | role="dialog", role="alert", role="tablist" |
Cuando un componente custom no tiene equivalente HTML suficiente. |
| ARIA states | Estado que cambia durante la interacción. | aria-expanded, aria-selected, aria-invalid |
Cuando el lector de pantalla debe conocer el estado actual. |
| ARIA properties | Nombre, descripción, relación o comportamiento. | aria-label, aria-describedby, aria-controls |
Cuando necesitás conectar controles, labels, ayuda o regiones dinámicas. |
Referencia oficial: W3C WAI-ARIA overview y MDN: Using ARIA roles, states and properties.
Roles ARIA más comunes
- role='navigation': marca una sección de navegación (aunque <nav> es preferible)
- role='dialog': para modales — indica al lector de pantalla que hay un diálogo superpuesto
- role='alert': para mensajes importantes que aparecen dinámicamente — se anuncia inmediatamente
- role='tablist', role='tab', role='tabpanel': para interfaces de pestañas accesibles
- role='menu', role='menuitem': para menús de acciones (no de navegación)
Properties y States ARIA esenciales
- aria-label: proporciona un nombre accesible cuando el texto visible no es suficiente — <button aria-label='Cerrar modal'>X</button>
- aria-labelledby: referencia otro elemento como label — útil cuando el label está en otro lugar del DOM
- aria-describedby: proporciona una descripción adicional — ideal para campos de formulario con instrucciones
- aria-expanded='true/false': indica si un acordeón, dropdown o menú está expandido o colapsado
- aria-hidden='true': oculta un elemento de las tecnologías asistivas (pero sigue visible) — para decoraciones
- aria-live='polite/assertive': anuncia contenido dinámico que cambia sin recargar la página (notificaciones, contadores)
aria-label, aria-labelledby y aria-describedby
Muchas búsquedas sobre ARIA vienen de una duda concreta: cómo dar nombre o contexto a un control. La regla práctica es simple:
aria-label: usalo cuando no hay texto visible suficiente, por ejemplo un botón solo con icono.aria-labelledby: usalo cuando el nombre accesible debe venir de otro elemento visible.aria-describedby: usalo para ayuda, error, restricción o explicación adicional.
<button aria-label="Cerrar modal">X</button>
<h2 id="billing-title">Datos de facturación</h2>
<section aria-labelledby="billing-title">
...
</section>
<label for="email">Email</label>
<input id="email" aria-describedby="email-help">
<p id="email-help">Usá el email donde querés recibir acceso.</p>
No dupliques nombres. Si el botón ya dice "Cerrar", normalmente no necesita aria-label="Cerrar".
Formularios accesibles con ARIA
- Cada input DEBE tener un label asociado: <label for='email'>Email</label><input id='email'>
- aria-required='true': indica que un campo es obligatorio (además del visual como asterisco)
- aria-invalid='true': marca un campo que tiene un error de validación
- aria-describedby: conecta mensajes de error o instrucciones con el campo correspondiente
- Grupos de radio buttons necesitan <fieldset> + <legend> para dar contexto al grupo completo
aria-required vs required
Para un <input>, <select> o <textarea> nativo, preferí required. Además de comunicar obligatoriedad, el navegador puede bloquear el envío inválido. aria-required="true" comunica el requisito a tecnologías asistivas, pero no agrega comportamiento ni validación por sí solo.
| Caso | Mejor opción | Razón |
|---|---|---|
| Input HTML real | required |
Semántica y validación nativa. |
Control custom con role="checkbox" |
aria-required="true" + JS |
ARIA comunica, JavaScript implementa comportamiento. |
| Label ya dice "obligatorio" | Evitar duplicación | Algunos lectores pueden anunciar "obligatorio" dos veces. |
Fuente: MDN aria-required.
Ejemplo práctico
<!-- Modal accesible -->
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">Confirmar eliminación</h2>
<p>¿Estás seguro de que quieres eliminar este archivo?</p>
<button>Cancelar</button>
<button>Eliminar</button>
</div>
<!-- Formulario accesible -->
<form>
<label for="email">Email *</label>
<input id="email" type="email" aria-required="true"
aria-invalid="true" aria-describedby="email-error">
<span id="email-error" role="alert">
Ingresá un email válido
</span>
</form>
Consejo: Probá siempre con un lector de pantalla real (VoiceOver o NVDA). Los ARIA attributes pueden verse correctos en el código pero sonar confusos cuando se anuncian en voz alta.
Checklist ARIA para revisar componentes reales
- Primero HTML: si existe
<button>,<nav>,<dialog>,<label>o<fieldset>, empezá ahí. - Nombre accesible: todo botón, input, enlace e icon button debe tener nombre entendible.
- Teclado: si usás
role="button", también necesitás foco, Enter, Space y estado visual. - Estados sincronizados:
aria-expanded,aria-selectedyaria-invaliddeben cambiar con la UI real. - No ocultar contenido útil:
aria-hidden="true"en contenido enfocable o importante suele romper la experiencia. - Probar de verdad: revisá con teclado, VoiceOver/NVDA y herramientas como axe o Lighthouse.
ARIA como habilidad laboral
ARIA es una señal fuerte para roles frontend, UX/UI, QA, producto y auditoría de accesibilidad porque conecta código con experiencia real. Convertí esta lección en portfolio auditando un componente: modal, tabs, menú, formulario o dropdown.
- Frontend: documentá HTML nativo usado, ARIA agregado, foco y comportamiento de teclado.
- QA: armá casos de prueba para lector de pantalla, tab order, errores y estados dinámicos.
- Freelance: ofrecé revisión de formularios, checkouts, dashboards y componentes custom.
Conectá esta habilidad con Frontend Developer, oportunidades en empleos y servicios de auditoría en el marketplace.