Skip to content

Asociación de errores de formulario (Screen Reader) ​

Rellenas un formulario, pulsas Enviar y debajo del campo de correo aparece en rojo "Este campo es obligatorio". Si usas un lector de pantalla, ese texto puede no existir para ti: al llegar al campo el lector dice "Correo electrónico, edición, en blanco" y nada más. No sabes por qué el envío no funcionó ni qué campo tienes que corregir.

Este test busca exactamente eso: mensajes de error que se ven en pantalla pero que el lector de pantalla no lee cuando el usuario llega al campo.

Alcance: qué errores llega a ver

La herramienta no escribe en los campos. Solo ve los mensajes de error que aparecen en dos situaciones:

  1. Al pulsar el botón de envío con los campos vacíos. El formulario tiene que tener un botón de envío reconocible (Enviar, Buscar, Continuar, Registrarse…).
  2. Al entrar y salir de un campo sin escribir, en los sitios que validan en el momento de abandonar el campo.

Un error que solo aparece cuando hay algo escrito (correo mal formado, contraseña demasiado corta, fechas incoherentes) queda fuera. Si un caso no encaja en esas dos situaciones, la herramienta no lo iba a reportar.


Qué revisa, en dos frases ​

  1. Que cada mensaje de error que aparece junto a un campo esté conectado a ese campo, de forma que el lector lo lea al enfocarlo.
  2. Que un campo que se ve en estado de error (borde o texto en rojo) también avise de que tiene un error, para que el lector diga "entrada inválida".

Lo primero es un issue del criterio WCAG 1.3.1. Lo segundo se reporta como Best Practice (buena práctica), no como incumplimiento.


Qué hace la herramienta ​

Hace lo mismo que haría una persona que se adelanta:

  1. Encuentra los formularios de la página. También los widgets que no son un formulario "de verdad" pero funcionan como tal: un buscador de vuelos o de hotel con su botón de Buscar, un bloque de newsletter con su botón de Enviar.
  2. Pulsa el botón de envío sin rellenar nada, con el teclado. La página no cambia de dirección; la herramienta lo impide para poder seguir mirando.
  3. Espera a que aparezcan los mensajes, incluidos los que tardan porque los valida el servidor o porque el formulario muestra un "cargando".
  4. Entra y sale de cada campo sin escribir, porque muchos sitios validan en el momento en que abandonas el campo.
  5. Comprueba cada mensaje y cada campo en rojo: si el mensaje está conectado al campo, y si el campo avisa de su error.

No escribe valores, no envía datos reales y no pasa de la primera pantalla del formulario.


Qué verás en el reporte ​

Los títulos salen en inglés, tal como los produce la herramienta.

"Errors not getting announced on the fields" ​

Es el issue principal. Significa que el mensaje existe en pantalla pero el lector de pantalla no lo lee al llegar al campo.

The screen reader does not announce the error message when the "Email" field is focused. The error message "This field is required." is visually displayed adjacent to the "Email" field, but there is no programmatic association between the field and the error message.

  • Ubicación / campo: el control afectado, con su nombre visible ("Email", "Desde", "Arrival city").
  • Otras ocurrencias: los demás campos de la misma página con el mismo problema. Un formulario con siete campos sin conectar es un issue con seis ocurrencias, no siete issues.
  • HTML: el campo y el mensaje tal como están en la página, para que desarrollo sepa qué tocar.
  • Cómo corregirlo: conectar el mensaje con el campo. En la práctica son dos cambios pequeños: darle un identificador al elemento del mensaje (si no lo tiene) y hacer que el campo lo referencie con aria-describedby. El reporte propone los nombres exactos y pide reutilizar el mensaje que ya existe, no crear uno nuevo.

Cuando el campo señala con aria-describedby a un identificador que no existe en la página, el reporte lo dice ("The field references id(s) [...] but no element with those ids exists").

"Field in error state is not marked as invalid" (Best Practice) ​

El campo se ve en error (rojo) pero no lo "dice": le falta aria-invalid="true", que es lo que hace que el lector anuncie "entrada inválida".

The "Email" field is visually displayed in an error state but does not advertise aria-invalid="true". Screen readers will not announce the field as invalid when it receives focus.

Cuándo salen juntos y cuándo separados ​

Si los mismos campos tienen los dos problemas, verás un solo issue del primer tipo, cuya corrección incluye también lo de aria-invalid. Si los campos no coinciden (por ejemplo, el mensaje sin conectar está en tres campos y solo dos carecen de aria-invalid, o uno de ellos es un botón selector donde aria-invalid no aplica), la Best Practice sale aparte con sus propios campos.


Cómo comprobarlo tú mismo ​

  1. Abre la página con NVDA (o JAWS, o VoiceOver en Mac).
  2. Pulsa el botón de envío con todos los campos vacíos. Si el sitio valida al salir del campo, entra en un campo obligatorio y sal con Tab sin escribir.
  3. Vuelve con Tab a un campo que muestre mensaje.
  4. Lo correcto es oír el nombre del campo, "entrada inválida" y el texto del mensaje.
  5. Si solo oyes el nombre del campo y "en blanco", el mensaje no está conectado (issue). Si oyes el mensaje pero no "entrada inválida", falta el aviso de error (Best Practice).

Para confirmar en el código: en las DevTools, el campo debería tener aria-describedby (o aria-errormessage) apuntando al id del elemento que contiene el mensaje, y aria-invalid="true" mientras el error está visible.


Qué no reporta (y no es un issue perdido) ​

Si un caso cae aquí, la herramienta no lo iba a reportar por diseño:

  • Resúmenes generales del formulario. "Por favor completa todos los campos obligatorios", "Hay 3 errores". Hablan del formulario entero, no de un campo, y no se asignan a ninguno.
  • Ayudas que ya estaban antes de enviar. "Ejemplo: dd/mm/aaaa", textos de formato, y los medidores de fortaleza de contraseña ("débil", "weak").
  • Campos que cambian "por dentro" pero no se ven en error. Un sitio puede marcar un campo como inválido en su código sin pintar nada en rojo. Si no hay cambio visual, no hay nada que anunciar.
  • Avisos de inválido puestos desde el principio. Algunos sitios marcan todos los campos obligatorios como inválidos desde que carga la página, sin que nadie los haya tocado. Se ignoran hasta que el campo se usa.
  • Mensajes que ya están conectados, aunque el identificador esté en el contenedor del mensaje y no en el texto mismo, o el mensaje viva dentro de la etiqueta del campo. El lector los lee igual.
  • Campos que el usuario no puede alcanzar: ocultos, en una pestaña inactiva o en un modal cerrado.
  • La burbuja de validación del navegador. Cuando el sitio deja que Chrome muestre su propio aviso ("Completa este campo"), no hay mensaje en la página que conectar; no se reporta nada salvo que el sitio además pinte el campo.
  • Mensajes que solo existen mientras el campo tiene el foco (burbujas flotantes que desaparecen al salir). Hoy no se tratan como mensaje del campo; el alcance de estos casos está pendiente de definir.

Dónde no llega ​

  • Formularios dentro de iframes (chats, widgets de reserva embebidos de otro dominio) y dentro de shadow DOM (por ejemplo, los bloques de newsletter de Shopify Forms). La herramienta no entra ahí.
  • Sitios que bloquean robots (una página de verificación con error 403). El test no llega a empezar.
  • Botones de envío que solo funcionan tras un paso previo (aceptar condiciones, captcha). Entonces solo se ve lo que el sitio valide al salir del campo.
  • Selectores a medida (ciudad, fecha) hechos con botones en lugar de campos. Se reconocen como el campo en error solo cuando se pintan en rojo o indican que abren un selector.
  • Páginas con muchísimos formularios. Hay un límite de tiempo por página y por formulario; lo que no da tiempo a revisar queda fuera y se anota en el registro de la ejecución.

Sitios ya validados ​

Resultados esperados hoy en algunos de los sitios usados en las rondas de QA. Sirven de referencia: si uno de estos da otra cosa, vale la pena revisarlo.

SitioQué tieneResultado esperado
cuba.cu (formulario de contacto del pie)mensajes sin conectar; solo el correo avisa de su error1 issue + 2 ocurrencias; 1 Best Practice + 1 ocurrencia
tricot.cl (registro)mensajes conectados, campos sin aviso de error1 Best Practice + 6 ocurrencias
abc.cl (inicio de sesión)mensajes conectados a través de su contenedor1 Best Practice + 2 ocurrencias
cruzverde.cl (registro)nueve campos que validan al salir1 issue + 7 ocurrencias
theinnovators.networkvalidación en servidor con "cargando"1 issue (checkbox de consentimiento)
byd.com/ukmensajes con animación de entrada1 issue + 7 ocurrencias
royaltonresorts.comsolo los checkboxes se ven en error1 Best Practice + 1 ocurrencia
singaporeair.com (buscador de vuelos)botón selector de ciudad y un mensaje para dos fechas1 issue + 2 ocurrencias; 1 Best Practice + 1 ocurrencia
caribbean-airlines.com (buscador)widget sin formulario real1 issue + 1 ocurrencia (From, To)
skyairline.com (buscador)campos de solo lectura en rojo, sin mensaje1 Best Practice + 2 ocurrencias
airastana.com (buscador)solo un resumen general del formulario0 issues
idea.davison.com, semrush.comavisos correctos; medidor de contraseña0 issues

Fuera del alcance (ya acordado en el ticket): tarjetacencosud.cl (toda la página es un iframe de otro dominio), fashionspark.com (newsletter en shadow DOM), servefirst.co.uk (formulario de HubSpot en iframe).


Para el equipo técnico ​

  • Nombre del test en el catálogo: form_error_association_async (categoría Screen Reader).
  • El detalle de cada regla, los pasos internos, las variables de configuración y el diagnóstico están en la página técnica del repositorio: Important Documentation/WCAG CP/1.3.1 - Info and Relationships/form-error-association-test.md.
  • Ticket de desarrollo y rondas de QA: a11y-issue-detector #1425.

Referencia WCAG ​

Criterio de éxito 1.3.1 Información y relaciones (Nivel A), con 3.3.1 Identificación de errores (Nivel A) como criterio compañero para el propio mensaje.