Accesibilidad Web - La Guía Definitiva que Todo Desarrollador Frontend Debe Conocer

8 de abril de 20257 min de lectura
Accesibilidad Web - La Guía Definitiva que Todo Desarrollador Frontend Debe Conocer

Aprende las mejores prácticas de accesibilidad web que transformarán tu código frontend y ampliarán el alcance de tus aplicaciones.

Por qué la accesibilidad web ya no es opcional en 2025

Hace unos años, cuando empecé en el desarrollo web, la accesibilidad era ese tema que "algún día" abordaría en mis proyectos. Ya sabéis cómo va esto: siempre hay features más urgentes, el cliente no lo pide explícitamente, el presupuesto es ajustado... y acabamos postergándolo. Hasta que un día, en un proyecto para una entidad pública, me vi obligado a cumplir con niveles WCAG AA. Y ahí descubrí que no solo estaba haciendo lo correcto, sino que mi código mejoraba notablemente.

La realidad es que en 2025, con las normativas actuales (como la Directiva Europea de Accesibilidad Web que ya se aplica a todos los sitios públicos y privados), ignorar la accesibilidad puede tener consecuencias legales. Pero más allá de eso, como desarrolladores, ¿no deberíamos construir productos que todo el mundo pueda usar? Al fin y al cabo, aproximadamente el 15% de la población mundial tiene algún tipo de discapacidad.

En este artículo voy a compartir lo que he aprendido tras varios proyectos donde la accesibilidad era un requisito crítico. No son conceptos complicados, pero marcan una diferencia enorme en la experiencia de muchos usuarios.

Las cuatro claves de la accesibilidad digital: POUR

Si habéis investigado algo sobre accesibilidad, seguramente habréis encontrado el acrónimo POUR. Si no, os lo presento:

  1. Perceptible: La información debe ser presentable de formas que cualquier usuario pueda percibir.
  2. Operable: Los elementos de la interfaz deben ser manejables por cualquier persona.
  3. Comprensible: Tanto la información como las operaciones deben ser fáciles de entender.
  4. Robusto: El contenido debe ser compatible con diferentes tecnologías y dispositivos, especialmente con tecnologías asistivas.

Estos principios no son solo teoría: son tremendamente prácticos para organizar nuestro enfoque.

HTML semántico: deja de usar divs para todo (en serio)

Vale, seamos sinceros. ¿Cuántos de vosotros seguís creando interfaces enteras a base de <div> y <span>? No os juzgo, yo también lo hacía. Hasta que entendí que estaba complicando la vida a los usuarios de lectores de pantalla.

Este es uno de los errores más comunes que veo en código de otros desarrolladores:

<!-- ❌ Así NO: El típico "div-itis" -->
<div class="header">
  <div class="logo">Mi Sitio Web</div>
  <div class="navigation">
    <div class="nav-item">Inicio</div>
    <div class="nav-item">Servicios</div>
    <div class="nav-item">Contacto</div>
  </div>
</div>
<div class="content">
  <div class="title">Bienvenidos a mi sitio</div>
  <div class="text">Este es el contenido principal...</div>
</div>

El problema es que este código no transmite ninguna estructura a las tecnologías asistivas. Para un lector de pantalla, esto es solo un montón de texto sin jerarquía.

En lugar de eso, usad elementos semánticos:

<!-- ✅ Así SÍ: Con semántica -->
<header>
  <h1>Mi Sitio Web</h1>
  <nav>
    <ul>
      <li><a href="/">Inicio</a></li>
      <li><a href="/servicios">Servicios</a></li>
      <li><a href="/contacto">Contacto</a></li>
    </ul>
  </nav>
</header>
<main>
  <h2>Bienvenidos a mi sitio</h2>
  <p>Este es el contenido principal...</p>
</main>

La semántica no solo mejora la accesibilidad, también hace vuestro código más mantenible y mejora el SEO. ¿Tres beneficios en uno? No hay excusa para no hacerlo.

Formularios: el gran dolor de cabeza de la accesibilidad

Por mi experiencia, los formularios son el punto donde más suelen fallar las webs en términos de accesibilidad. Y es una pena, porque hay soluciones sencillas:

Etiquetas explícitas con for

Estoy seguro de que habéis visto (o incluso escrito) código como este:

<!-- ❌ Mal: Sin etiqueta o con etiqueta no asociada -->
<div>Email:</div>
<input type="email" placeholder="Tu email" />

El problema es que la etiqueta no está asociada al campo, lo que complica la vida a usuarios de lectores de pantalla. La solución es simple:

<!-- ✅ Bien: Con etiqueta asociada correctamente -->
<label for="email">Email:</label>
<input id="email" type="email" />

No uses solo el color para indicar estados

Hace poco revisaba un formulario donde los campos con error se marcaban solo en rojo. Esto es problemático para personas con daltonismo. En su lugar:

<!-- ✅ Mejor: Combinando color y texto -->
<label for="email">Email:</label>
<input id="email" type="email" aria-describedby="email-error" aria-invalid="true" />
<p id="email-error" class="error-text">
  <span aria-hidden="true">❌</span> 
  Por favor, introduce un email válido.
</p>

Y en el CSS:

.error-text {
  color: #d32f2f; /* Un rojo que cumple con contraste */
  font-weight: bold;
  /* Añadir también un indicador que no sea solo color */
  border-left: 4px solid #d32f2f;
  padding-left: 8px;
}

Gestión del foco

Algo que suelo implementar en mis proyectos es un buen manejo del foco, especialmente después de enviar un formulario.

Si el formulario tiene errores, el foco debería moverse al primer campo con error:

// Después de validar el formulario y encontrar errores
const primerCampoConError = document.querySelector('[aria-invalid="true"]');
if (primerCampoConError) {
  primerCampoConError.focus();
}

Y si el envío es exitoso, el foco debería ir al mensaje de confirmación:

// Tras envío exitoso
const mensajeExito = document.getElementById('mensaje-exito');
mensajeExito.setAttribute('tabindex', '-1');
mensajeExito.focus();

Estos pequeños detalles mejoran enormemente la navegación por teclado.

Contraste y diseño visual

Vamos a hablar de diseño visual, que también tiene mucho que ver con la accesibilidad. Uno de los problemas más comunes que encuentro es el bajo contraste de texto.

Las pautas WCAG exigen:

  • Ratio de contraste de al menos 4.5:1 para texto normal
  • Ratio de 3:1 para texto grande (más de 24px o 18px en negrita)

Yo uso Contrast Finder para comprobar mis combinaciones de color. El típico gris claro sobre blanco que tanto se usa no suele cumplir estos requisitos. Probad con #595959 como mínimo para texto sobre fondo blanco.

Otra recomendación que siempre doy: no os fiéis solo de vuestros ojos. Usad herramientas como Stark o Color Oracle para simular diferentes tipos de daltonismo.

Interactividad y comportamiento

Un aspecto que me parece fundamental es cómo interactúan los usuarios con elementos dinámicos.

Carruseles y contenido en movimiento

Si implementáis un carrusel (aunque personalmente los detesto por razones de usabilidad), aseguraos de:

  • Incluir controles para pausar la animación
  • Proporcionar controles de navegación accesibles
  • No auto-reproducir si el usuario ha indicado preferencia por movimiento reducido
@media (prefers-reduced-motion) {
  .carousel {
    animation: none;
    transition: none;
  }
}

Modales y ventanas emergentes

Los modales son otro elemento problemático. Cuando abro un modal, siempre:

  1. Capturo el foco dentro del modal (trampa de foco)
  2. Devuelvo el foco al elemento que lo abrió cuando se cierra
  3. Permito cerrar con ESC
  4. Asigno role="dialog" y aria-modal="true"
// Ejemplo básico de trampa de foco
function trapFocusInModal(modalElement) {
  const focusables = modalElement.querySelectorAll(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  
  const firstFocusable = focusables[0];
  const lastFocusable = focusables[focusables.length - 1];
  
  // Circular el foco de último a primero
  lastFocusable.addEventListener('keydown', (e) => {
    if (e.key === 'Tab' && !e.shiftKey) {
      e.preventDefault();
      firstFocusable.focus();
    }
  });
  
  // Circular el foco de primero a último
  firstFocusable.addEventListener('keydown', (e) => {
    if (e.key === 'Tab' && e.shiftKey) {
      e.preventDefault();
      lastFocusable.focus();
    }
  });
  
  // Inicialmente dar foco al primer elemento
  firstFocusable.focus();
}

Testing de accesibilidad: herramientas imprescindibles

Por último, quiero compartir mi stack de herramientas para testing de accesibilidad:

  1. axe DevTools: Una extensión de navegador que uso a diario para detectar problemas básicos.
  2. WAVE: Otra extensión que ofrece un enfoque visual de los problemas.
  3. Lighthouse: Integrado en Chrome DevTools, tiene una sección de accesibilidad.
  4. NVDA (Windows) o VoiceOver (Mac): Lectores de pantalla para testing real.

Pero la herramienta más importante es... la navegación por teclado. Intenta usar tu propia web sin ratón durante 5 minutos. Te sorprenderá lo que descubres.

Más allá del cumplimiento: accesibilidad como mejora para todos

Para terminar, quiero enfatizar algo: la accesibilidad no es solo para personas con discapacidades permanentes. Todos nos beneficiamos de un diseño más accesible:

  • Las transcripciones de audio ayudan cuando estás en un entorno ruidoso.
  • El alto contraste es útil cuando usas el móvil bajo luz solar directa.
  • La navegación por teclado es esencial para usuarios avanzados.
  • Los subtítulos ayudan a quienes no dominan el idioma.

Por eso no veo la accesibilidad como un requisito molesto sino como una oportunidad para mejorar la experiencia de todos los usuarios.

¿Qué opináis? ¿Implementáis estas prácticas en vuestros proyectos? ¿Habéis tenido alguna experiencia particular con la accesibilidad web? Me encantaría leer vuestros comentarios.

Compartir este artículo

Última actualización: 8 de abril de 2025

Si te ha gustado este artículo, no dudes en compartirlo con tus colegas o dejar un comentario.