Accesibilidad web: lo mínimo que todo frontend debería saber

La accesibilidad ya no es una opción, es una obligación legal y ética. Como frontend, puedes lograr que tu sitio sea usable por la mayor parte de la población sin escribir código complejo. En este artículo repasamos los conceptos esenciales que deberías aplicar en cada proyecto.
1. Usa la semántica HTML adecuada
El primer paso es confiar en las etiquetas nativas. Un <button> ya es focoable y anuncia su rol a los lectores de pantalla. Evita <div> o <span> para interacciones y, si lo haces, añade los atributos necesarios (role, tabindex, etc.).
2. Imágenes con texto alternativo
Todo <img> debe llevar alt. Si la imagen es decorativa, usa alt="" para que los lectores la ignoren. En imágenes que transmiten información, el texto alternativo debe ser conciso y descriptivo.
3. Contraste de colores
El contraste entre texto y fondo debe ser de al menos 4.5:1 para texto normal y 3:1 para texto grande. Herramientas como WebAIM Contrast Checker te facilitan la comprobación.
4. Navegación con teclado
Todos los elementos interactivos deben ser accesibles sin ratón. Usa tabindex="0" sólo cuando sea necesario y evita tabular a elementos invisibles. Un buen patrón es cerrar modales con Esc y devolver el foco al elemento que los abrió.
5. Roles y atributos ARIA
ARIA no es un sustituto de la semántica, sino un complemento. Utilízalo cuando no exista un elemento nativo que describa la función. Algunos casos típicos:
- role="alert" para mensajes urgentes.
- aria-live="polite" para actualizaciones dinámicas que no interrumpen.
- aria-expanded en botones que despliegan contenido.
6. Formularios accesibles
Asocia cada <input> con su <label> usando el atributo for. Los mensajes de error deben estar vinculados mediante aria-describedby y anunciados al lector de pantalla.
7. Ejemplo práctico: botón accesible
A continuación, un componente simple que muestra cómo combinar semántica, foco y ARIA para crear un botón que abre un menú.
<button id="menuBtn" aria-haspopup="true" aria-controls="menu" aria-expanded="false">Opciones</button>
<ul id="menu" role="menu" hidden>
<li role="menuitem" tabindex="-1">Perfil</li>
<li role="menuitem" tabindex="-1">Configuración</li>
<li role="menuitem" tabindex="-1">Cerrar sesión</li>
</ul>
<script>
const btn = document.getElementById('menuBtn');
const menu = document.getElementById('menu');
btn.addEventListener('click', () => {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', !expanded);
menu.hidden = expanded;
// Cuando abrimos, movemos el foco al primer ítem
if (!expanded) {
const firstItem = menu.querySelector('[role="menuitem"]');
firstItem.setAttribute('tabindex', '0');
firstItem.focus();
}
});
// Cerrar con Escape y volver al botón
document.addEventListener('keydown', e => {
if (e.key === 'Escape' && !menu.hidden) {
menu.hidden = true;
btn.setAttribute('aria-expanded', 'false');
btn.focus();
}
});
</script>
Observa cómo:
- El
buttonindica que abre un menú (aria-haspopup). - Se controla el estado abierto/cerrado con
aria-expanded. - Los ítems del menú usan
role="menuitem"y reciben foco sólo cuando el menú está visible.
8. Testing y auditoría
Incluye pruebas de accesibilidad en tu flujo CI. Herramientas como axe-core o npm run test:accessibility detectan problemas comunes. Además, revisa manualmente con lectores de pantalla (NVDA, VoiceOver) y prueba la navegación con Tab y Shift+Tab.
9. Checklist rápido
- ¿Todas las imágenes tienen
altadecuado? - ¿Los colores cumplen el contraste mínimo?
- ¿Todo elemento interactivo es focoable y operable con teclado?
- ¿Se usan roles/ARIA sólo cuando es necesario?
- ¿Los formularios tienen
labely mensajes de error accesibles?
Aplicando estos puntos básicos, tu proyecto ganará en usabilidad, SEO y cumplimiento normativo. La accesibilidad no es una capa extra, es parte del núcleo del desarrollo frontend.