1. ¿Qué es la Accesibilidad Web?
La accesibilidad web (a11y) se refiere a diseñar sitios web que puedan ser usados por todas las personas, incluyendo aquellas con discapacidades visuales, auditivas, motoras o cognitivas.
- ?? Ética: La web debe ser para todos
- ?? Legal: Muchos países exigen accesibilidad por ley
- ?? SEO: Los buscadores valoran la accesibilidad
- ?? Negocio: Más usuarios = más clientes potenciales
Usuarios que se benefician:
- Personas ciegas: Usan lectores de pantalla (NVDA, JAWS, VoiceOver)
- Personas con baja visión: Necesitan contraste, zoom, textos grandes
- Personas con discapacidad motora: Navegan solo con teclado
- Personas con discapacidad auditiva: Requieren subtítulos y transcripciones
- Personas mayores: Pueden tener dificultades visuales o motoras
2. ¿Qué es ARIA?
ARIA (Accessible Rich Internet Applications) es un conjunto de atributos HTML que mejoran la accesibilidad de aplicaciones web dinámicas. Fue creado por el W3C para llenar los vacíos que el HTML semántico no cubre.
Siempre usa HTML semántico primero. ARIA solo debe usarse cuando el HTML nativo no es suficiente.
<!-- MAL: Usar ARIA cuando existe HTML semántico -->
<div role="button" tabindex="0">Clic aquí</div>
<!-- BIEN: Usar el elemento HTML correcto -->
<button>Clic aquí</button>
3. aria-label y aria-labelledby
aria-label
Proporciona una etiqueta de texto que describe el elemento. Útil cuando no hay texto visible.
<!-- Botón con ícono sin texto -->
<button aria-label="Cerrar modal">?</button>
<button aria-label="Buscar en el sitio">??</button>
aria-labelledby
Indica que el elemento está etiquetado por otro elemento existente mediante su ID.
Configuración de Privacidad
Aquí puedes configurar tus preferencias de privacidad...
<h3 id="titulo-seccion">Configuración de Privacidad</h3>
<div aria-labelledby="titulo-seccion">
<p>Aquí puedes configurar tus preferencias...</p>
</div>
4. aria-describedby
Proporciona una descripción adicional del elemento. Perfecto para mensajes de ayuda o errores.
<label for="password">Contraseña:</label>
<input type="password" id="password" aria-describedby="password-help">
<small id="password-help">Mínimo 8 caracteres, incluye números y símbolos</small>
5. Roles (role)
El atributo role define qué tipo de elemento es. Úsalo solo cuando el HTML semántico no
sea suficiente.
Roles comunes:
| Role | Descripción | HTML Equivalente |
|---|---|---|
role="banner" |
Encabezado principal del sitio | <header> |
role="navigation" |
Navegación principal | <nav> |
role="main" |
Contenido principal | <main> |
role="contentinfo" |
Pie de página | <footer> |
role="search" |
Región de búsqueda | No hay equivalente |
role="alert" |
Mensaje importante/urgente | No hay equivalente |
<!-- Región de búsqueda -->
<div role="search">
<label for="busqueda">Buscar:</label>
<input type="search" id="busqueda">
<button>Buscar</button>
</div>
6. Estados y Propiedades ARIA
aria-expanded
Indica si un elemento desplegable está abierto o cerrado.
<button aria-expanded="false">Mostrar más</button>
<!-- Cuando se expande -->
<button aria-expanded="true">Ocultar</button>
aria-hidden
Oculta elementos de lectores de pantalla (aunque sigan visibles visualmente).
<!-- Icono decorativo -->
<span aria-hidden="true">??</span> Color
<!-- Modal cerrado -->
<div class="modal" aria-hidden="true">...</div>
aria-disabled
Indica que un elemento está deshabilitado.
<button aria-disabled="true">Enviar (deshabilitado)</button>
aria-required
Indica que un campo es obligatorio.
<input type="text" aria-required="true">
aria-invalid
Indica que un campo tiene un error de validación.
<input type="email" aria-invalid="true" aria-describedby="email-error">
<span id="email-error">El email no es válido</span>
7. Ejemplos Prácticos
?? Formulario Accesible
<form>
<div>
<label for="nombre">Nombre: <span aria-label="obligatorio">*</span></label>
<input type="text" id="nombre" aria-required="true" required>
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" aria-describedby="email-ayuda">
<small id="email-ayuda">Usaremos tu email para confirmar tu cuenta</small>
</div>
<button type="submit">Enviar</button>
</form>
?? Notificación (Live Region)
aria-live comunica cambios dinámicos a lectores de pantalla.
<div role="alert" aria-live="polite">
? Guardado correctamente
</div>
<!-- aria-live valores -->
<!-- "polite": Espera a que el usuario termine -->
<!-- "assertive": Interrumpe al usuario (solo para urgencias) -->
8. Navegación por Teclado
La accesibilidad por teclado es fundamental. Todos los elementos interactivos deben ser accesibles con Tab, Enter y Espacio.
Atributo tabindex
tabindex="0": Elemento enfocable en orden naturaltabindex="-1": Enfocable programáticamente, no con Tabtabindex="1+": ?? Evitar (rompe el orden lógico)
<!-- Div clickeable accesible por teclado -->
<div role="button" tabindex="0" onclick="..." onkeypress="...">
Clic aquí
</div>
- ? Usa siempre
<button>en lugar de<div>clickeable - ? Asegúrate de que el foco sea visible (outline)
- ? Testea tu sitio navegando solo con teclado
- ? Soporta Escape para cerrar modales
9. Técnicas de Texto Oculto Visualmente
A veces necesitas texto para lectores de pantalla que no debe ser visible.
<style>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<button>
<span class="visually-hidden">Eliminar</span>
???
</button>
10. Herramientas de Testing
Extensiones de Navegador:
- axe DevTools: Analiza accesibilidad automáticamente
- WAVE: Evaluador visual de accesibilidad
- Lighthouse: Incluido en Chrome DevTools
Lectores de Pantalla:
- NVDA: Gratis para Windows
- JAWS: Profesional para Windows (pago)
- VoiceOver: Integrado en macOS/iOS
- TalkBack: Integrado en Android
Test Manual Básico:
- Navega todo el sitio solo con Tab
- Verifica que el foco sea visible
- Usa un lector de pantalla (ej: NVDA)
- Aumenta el zoom al 200%
- Desactiva CSS para ver solo el HTML
11. Checklist de Accesibilidad
- ?? Todas las imágenes tienen
alt - ?? Los formularios tienen
<label>correctamente asociados - ?? Hay suficiente contraste de color (mínimo 4.5:1)
- ?? El sitio funciona solo con teclado
- ?? El foco es visible
- ?? Los encabezados están en orden lógico (h1, h2, h3...)
- ?? Los enlaces tienen texto descriptivo (no "clic aquí")
- ?? El contenido dinámico usa
aria-live - ?? Los modales tienen
aria-hiddeny gestionan el foco - ?? Usas HTML semántico antes que ARIA
12. Recursos Adicionales
- WCAG 2.1: Pautas oficiales de accesibilidad (W3C)
- MDN ARIA: https://developer.mozilla.org/es/docs/Web/Accessibility/ARIA
- WebAIM: https://webaim.org/
- A11y Project: https://www.a11yproject.com/
? Errores Comunes
- Usar
roleen elementos HTML nativos:<button role="button">es redundante - Olvidar
alten imágenes: Deja ciegos a los lectores de pantalla - Hacer divs clickeables: Usa
<button> - Texto muy pequeño: Mínimo 16px
- Poco contraste: Usa herramientas como Contrast Checker
- Modales sin gestión de foco: El foco debe ir al modal y volver al elemento que lo abrió