Los formularios son el punto en el que tu web deja de hablar y se pone a escuchar: solicitudes de contacto, pedidos, registros, búsquedas. También son donde más a menudo falla la accesibilidad. El estudio WebAIM Million, que analiza cada año el millón de páginas de inicio más visitadas, encuentra de forma sistemática etiquetas ausentes en los campos de formulario en casi la mitad de ellas, lo que lo convierte en uno de los fallos de accesibilidad más comunes de la web. Lo frustrante es que los formularios accesibles no son difíciles. Un puñado de atributos HTML bien usados decide si una persona ciega puede enviarte un mensaje o se rinde en silencio, y si tu formulario cumple las WCAG, algo que la Ley Europea de Accesibilidad ha convertido en requisito legal para muchas empresas. Esta guía repasa las cinco cosas que importan, con marcado listo para copiar y pegar, y termina con una mirada honesta a los plugins de formularios de WordPress.
¿Por qué los formularios son el mayor problema de accesibilidad?
Quien ve la pantalla y usa el ratón lee el formulario como un conjunto visual: el texto junto a una caja pertenece obviamente a esa caja, el borde rojo significa obviamente un error. La tecnología de apoyo no tiene nada de ese contexto. Quien usa un lector de pantalla va tabulando de control en control y solo oye lo que el marcado conecta explícitamente con cada campo. Si falta la conexión, oye campo de texto, vacío, y tiene que adivinar qué pide el campo. Quien usa control por voz se enfrenta a un problema paralelo: decir haz clic en email solo funciona si el campo se llama email a nivel de programación.
Ese es el principio de fondo de todas las reglas de esta guía: toda relación visual de un formulario tiene que existir también en el marcado. Etiqueta con campo, pista con campo, error con campo, grupo con opciones. Los criterios de conformidad de las WCAG que aplican (1.3.1 Info and Relationships, 3.3.1 Error Identification, 3.3.2 Labels or Instructions) se reducen todos a esta misma idea.
Cómo etiquetar correctamente los campos de un formulario
La base de todo formulario accesible es el elemento label, conectado a su campo con el atributo for que apunta al id del campo:
<label for="email">Dirección de correo electrónico</label>
<input type="email" id="email" name="email" autocomplete="email">
<!-- Pista adicional, conectada mediante aria-describedby -->
<label for="password">Contraseña</label>
<input type="password" id="password" name="password" aria-describedby="password-hint">
<p id="password-hint">Al menos doce caracteres.</p>Esto te da tres cosas a la vez: los lectores de pantalla anuncian la etiqueta cuando el campo recibe el foco, hacer clic en la etiqueta pone el foco en el campo (un objetivo táctil más grande en móvil, para todo el mundo) y el control por voz puede dirigirse al campo por su nombre. Las pistas y las instrucciones de formato van en un elemento aparte referenciado con aria-describedby, así se anuncian después de la etiqueta sin recargarla. El atributo autocomplete es un extra discreto: para los campos que recogen datos personales, las WCAG 1.3.5 lo piden, y permite que los navegadores rellenen el campo correctamente, algo que ayuda sobre todo a las personas con limitaciones motrices y cognitivas. El tutorial de formularios del W3C cubre todas las variantes de estos patrones.
Por qué un placeholder no es una etiqueta
El campo de formulario solo con placeholder es el error con apariencia accesible más común de la web. Se ve limpio y falla de cuatro maneras a la vez:
- El texto desaparece al escribir. La descripción se esfuma justo cuando la persona está trabajando con el campo. Cualquiera que haya olvidado qué pedía un campo a medio rellenar ha sentido esto.
- El gris por defecto incumple el contraste. El estilo típico de placeholder no alcanza la relación de contraste de 4,5:1 que las WCAG exigen para el texto.
- El soporte de las tecnologías de apoyo es irregular. Algunas combinaciones de lector de pantalla y navegador anuncian los placeholders y otras no. Una etiqueta la anuncian todas.
- Los campos rellenos parecen vacíos y los vacíos parecen rellenos. Quien repasa el formulario buscando qué le falta lo interpreta al revés.
Los placeholders están bien como complemento, por ejemplo como muestra de formato tipo nombre@example.com dentro de un campo bien etiquetado. Como única descripción de un campo son un incumplimiento de las WCAG 3.3.2 con buena tipografía.
Cómo marcar los campos obligatorios de forma accesible
Dos canales, siempre juntos. El canal de máquina es el atributo required de HTML, que hace que navegadores y lectores de pantalla anuncien el campo como obligatorio y activa la validación nativa. El canal humano es el texto visible: la palabra obligatorio (o su contraria, opcional) dentro de la etiqueta. El popular asterisco rojo por sí solo falla en ambos frentes: el color por sí solo no puede transmitir información (WCAG 1.4.1) y la convención del asterisco, si aun así la usas, debe al menos explicarse encima del formulario e incluirse en la etiqueta para que se anuncie.
<label for="name">Nombre (obligatorio)</label>
<input type="text" id="name" name="name" required>Una inversión pragmática produce a menudo los formularios más limpios: si casi todos los campos son obligatorios, marca solo los opcionales y dilo encima del formulario. Y el mejor campo obligatorio es el que eliminas; cada campo que un formulario no pide es un campo que no se puede rellenar mal.
Cómo hacer accesibles los mensajes de error
El tratamiento de errores es donde los formularios pierden a las personas que aún no habían perdido. Las WCAG 3.3.1 exigen que los errores se identifiquen en texto y se describan a quien los provoca. El patrón robusto por campo:
<label for="email">Dirección de correo electrónico (obligatorio)</label>
<input type="email" id="email" name="email" required
aria-invalid="true" aria-describedby="email-error">
<p id="email-error" class="error">
Introduce una dirección de correo electrónico, por ejemplo nombre@example.com.
</p>Las piezas: aria-invalid="true" marca el campo como erróneo para que los lectores de pantalla anuncien entrada no válida al enfocarlo, el mensaje es texto de verdad (no solo un borde rojo, no solo un icono) y está atado al campo con aria-describedby, y la redacción dice cómo arreglar el problema, no solo que existe. Error, corrígelo no ayuda a nadie; Introduce una fecha con el formato DD/MM/AAAA sí.
Para la validación que se ejecuta al enviar, importa un paso más: tras un envío fallido, lleva el foco del teclado al primer campo erróneo o renderiza arriba un resumen de errores con role="alert" y enlaces a los campos afectados. Quien usa un lector de pantalla y envía sin oír nada da por hecho que el formulario ha funcionado. El silencio tras un envío fallido es el error de formulario más cruel que existe.
Fieldset y legend: agrupar botones de opción y casillas
Los grupos de botones de opción y de casillas tienen una estructura de dos niveles: el grupo plantea una pregunta y cada opción tiene su etiqueta. Ambos niveles deben estar en el marcado, y los elementos nativos para el nivel de grupo son fieldset y legend:
<fieldset>
<legend>Método de contacto preferido (obligatorio)</legend>
<input type="radio" id="contact-email" name="contact" value="email">
<label for="contact-email">Correo electrónico</label>
<input type="radio" id="contact-phone" name="contact" value="phone">
<label for="contact-phone">Teléfono</label>
</fieldset>Sin el fieldset, quien usa un lector de pantalla y tabula hasta el grupo solo oye Correo electrónico, botón de opción, uno de dos, y no tiene ni idea de a qué pregunta responden las opciones. Con él, la leyenda se anuncia primero. La misma estructura sirve para los grupos de casillas y merece la pena mantenerla aunque un sistema de diseño reestilice los elementos hasta hacerlos irreconocibles; la semántica no cuesta nada y lo aporta todo.
¿Son accesibles los plugins de formularios de WordPress?
En general pueden serlo, y ninguno lo garantiza. El panorama honesto plugin por plugin: Contact Form 7 renderiza lo que escribas en su plantilla de formulario, así que las etiquetas, los fieldsets y el cableado de errores están enteramente en tus manos; la flexibilidad que lo hace popular también hace fácil publicar formularios sin etiquetas. Gravity Forms rehízo su marcado con la accesibilidad como objetivo explícito hace unos años y produce una salida sólida en las versiones actuales. WPForms también ha invertido en valores por defecto accesibles. En todos los casos hay tres cosas que aún pueden romper un plugin accesible: los estilos de tu tema (contornos de foco eliminados, contraste destrozado), los CAPTCHA (una barrera completamente inaccesible; los enfoques con honeypot evitan el problema) y los tipos de campo personalizados añadidos encima.
Así que prueba el resultado renderizado, no la página de marketing. La versión de dos minutos: desenchufa el ratón y completa el formulario solo con el teclado, comprobando que ves el foco en cada paso, y luego envíalo vacío y comprueba si los mensajes de error se anuncian y son alcanzables. Los validadores automáticos como WAVE detectan en segundos la mitad estructural, incluidas las etiquetas ausentes.
Cómo te ayuda InspectWP a encontrar problemas en los formularios
El informe de InspectWP examina tu sitio WordPress renderizado tal y como lo ve un navegador, y varias comprobaciones tienen que ver directamente con los formularios. Señala los formularios cuyo action envía a una dirección HTTP insegura, un problema que los navegadores castigan con avisos justo en el momento en que una visita está a punto de confiarte sus datos. Más allá de eso, el informe cubre los fundamentos de accesibilidad que rodean a tus formularios: imágenes sin atributo alt, la jerarquía de encabezados con la que navegan quienes usan lector de pantalla y los errores de consola que a menudo delatan scripts de validación rotos. Un informe gratuito es una primera pasada rápida sobre la página en la que vive tu formulario.