ARIA: Cuando el HTML No es Suficiente
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 agregas 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
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)
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
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">
Por favor ingresa un email válido
</span>
</form>
Consejo: Prueba 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.