Mejora progresiva de formularios: crea formularios resistentes

Aprende la mejora progresiva de formularios. Crea formularios que funcionan sin JavaScript y mejóralos cuando el navegador lo permite.

Borrador

A un visitante se le corta internet mientras carga tu formulario. Una extensión de Chrome rompe tu JavaScript. Un navegador antiguo no admite el JavaScript que usas. Su lector de pantalla no puede recorrer tu formulario porque las etiquetas están ocultas con CSS.

Los formularios son rutas críticas. Los usuarios necesitan enviarlos. El formulario no puede simplemente romperse. La mejora progresiva es el principio de crear formularios que funcionen en todas partes y añadir después mejoras para los navegadores que puedan aprovecharlas.

Este artículo explica cómo crear formularios que se degraden con elegancia, funcionen sin JavaScript y sigan siendo accesibles para todos.

¿Qué es la mejora progresiva?

La mejora progresiva consiste en empezar con un formulario básico que funcione en los navegadores más antiguos y sin JavaScript, y añadir mejoras encima para los navegadores modernos. La capa 1 (HTML) ofrece un formulario básico con campos, etiquetas y un botón de envío que no necesita JavaScript y funciona en todas partes. La capa 2 (CSS) da estilo al formulario con colores, espacios y diseño, de modo que el formulario sigue funcionando si el CSS no se carga, aunque se vea mal. La capa 3 (JavaScript) añade validación en tiempo real, animaciones fluidas y envío por AJAX, de modo que el formulario sigue funcionando si falla JavaScript y simplemente se envía de la forma tradicional. Si falla cualquier capa, el usuario sigue teniendo un formulario que funciona. Eso es resistencia.

La base: HTML que funciona

Empieza con HTML semántico, con etiquetas, fieldsets y elementos legend bien usados. Un formulario base se parece a <form action="/submit" method="POST"> <label for="email">Email</label> <input type="email" id="email" name="email" required> <label for="message">Message</label> <textarea id="message" name="message" required></textarea> <button type="submit">Send</button> </form>. Este formulario funciona sin JavaScript, sin CSS, en navegadores antiguos, con lectores de pantalla y con navegación por teclado. Esta es tu base. No quites nunca elementos del DOM para sustituirlos por elementos generados con JavaScript, porque si el JavaScript falla, el formulario se rompe. Conserva el HTML semántico.

Degradación elegante con CSS

Añade las mejoras de CSS encima del HTML. Dale al formulario un buen estilo. Pero si el CSS falla, el formulario sigue funcionando.

No ocultes las etiquetas con CSS para apoyarte en los marcadores de posición, porque algunos CSS no se cargan y los lectores de pantalla necesitan las etiquetas en el HTML. No uses CSS para ocultar los indicadores de campo obligatorio, porque si tu "estrella de obligatorio" personalizada no se carga, los usuarios no pueden saber qué campos son obligatorios. Usa mejor el atributo required de HTML. Evita ocultar la etiqueta visualmente y mostrar en su lugar un marcador de posición con label { display: none; } y input::placeholder { content: 'Email'; }. En su lugar, conserva la etiqueta en el HTML y dale el estilo que quieras con label { font-weight: bold; color: #333; }.

Mejoras de JavaScript que se degradan bien

Añade mejoras de JavaScript, pero solo si el formulario ya funciona. Usa la detección de funciones para comprobar si el navegador admite lo que necesitas con if (window._blocked_) { // Use _blocked_ for AJAX submission } else { // Form submits traditionally }. No des por hecho que las funciones existen. Da por hecho que quizá no. Detecta primero.

Validación en tiempo real con alternativa

Usa la validación de HTML como base con <input type="email" required>, para que el navegador valide al enviar. Después añade una validación con JavaScript que se ejecute en tiempo real con input.addEventListener('blur', () => { if (!isValid(input.value)) { input.classList.add('invalid'); showError(input, 'Invalid email'); } });. Muestra los errores mientras el usuario escribe y, si JavaScript falla, la validación integrada del navegador sigue funcionando. El usuario se beneficia de la respuesta en tiempo real y, si JavaScript falla, recibe la respuesta del navegador al enviar. En cualquier caso, la validación se hace.

Envío por AJAX con alternativa tradicional

Crea un formulario tradicional que se envíe al servidor, intercepta después el envío y usa AJAX en su lugar con form.addEventListener('submit', async (e) => { e.preventDefault(); const response = await _blocked_('/submit', { method: 'POST', body: new FormData(form) }); if (response.ok) { showMessage('Success'); } });. Si JavaScript falla, preventDefault nunca se ejecuta, el formulario se envía de la forma tradicional y el usuario ve una recarga de página en lugar de una experiencia fluida. Pero el formulario funciona.

La accesibilidad como mejora progresiva

La accesibilidad no es una función extra. Es la base. Crea formularios accesibles.

Las etiquetas deben vincularse a los campos con los atributos for e id. No con atributos data ni con aria-labels que pueden pasarse por alto. Etiquetas de verdad.

<label for="email">Email</label>

<input id="email">

Usa elementos HTML semánticos (fieldset, legend, button, input). No divs con aspecto de botón.

La navegación por teclado debe funcionar. Tab para recorrer todos los campos. Mayús+Tab para volver atrás. Intro para enviar. Espacio para marcar casillas. Esto funciona por defecto con HTML semántico. No lo rompas con JavaScript.

Cuando lo básico funcione, añade etiquetas ARIA para los lectores de pantalla. Añade indicadores de foco para quienes usan el teclado. Pero son mejoras sobre un HTML ya accesible.

Pruebas de resistencia

Prueba tu formulario con JavaScript desactivado. Desactiva JavaScript en tu navegador e intenta enviarlo. Si el formulario se rompe, no es resistente.

Prueba con redes lentas. Limita tu conexión a 2G. Si el formulario tarda una eternidad en cargarse, los visitantes con internet inestable se irán.

Prueba con navegadores antiguos. Usa una herramienta de pruebas en varios navegadores para comprobar IE 11 (si todavía lo necesitas). Mira qué funciones no se admiten.

Prueba con lectores de pantalla. Usa uno para Windows o para Mac. Escucha cómo anuncia el formulario. Si no tiene sentido para un lector de pantalla, arréglalo.

Prueba solo con el teclado. No uses el ratón. ¿Puedes recorrer el formulario? ¿Puedes enviarlo?

Detección de funciones, no de navegadores

No compruebes navegadores concretos. Comprueba funciones, en lugar de usar una detección de navegador como if (navigator.userAgent.includes('Chrome')) { /* use _blocked_ */ }. Usa mejor la detección de funciones, como if (window._blocked_) { /* use _blocked_ */ }. La detección de funciones es más fiable, porque una actualización del navegador que añada compatibilidad con _blocked_ funcionará con tu código, pero la detección de navegador no.

Cómo crea WEMASY formularios resistentes

Los formularios de WEMASY se crean con principios de mejora progresiva: funcionan sin JavaScript, tienen etiquetas y HTML semántico, y las mejoras de JavaScript son opcionales, de modo que los navegadores antiguos reciben un formulario que funciona y los modernos disfrutan de interacciones fluidas.

Consulta las funciones de resistencia en tu plan de WEMASY.

Preguntas frecuentes

¿Mi formulario necesita funcionar de verdad sin JavaScript?
En los formularios críticos (contacto, pago, registro), sí. Algunos usuarios tienen JavaScript desactivado o roto. Algunos scripts fallan con redes inestables. Algunos navegadores antiguos no admiten el JavaScript moderno. Crear una alternativa garantiza que todos puedan usar tu formulario. Con el creador de webs de WEMASY puedes configurarlo directamente en tu web.
¿Cómo compruebo si mi formulario funciona sin JavaScript?
Desactiva JavaScript en tu navegador. En Chrome: Configuración > Privacidad > Configuración de contenido > JavaScript > Desactivado. En otro navegador: about:config > javascript.enabled > false. Intenta enviar el formulario. Si falla, tu formulario no es resistente.
¿Qué es la detección de funciones y por qué es mejor que la detección de navegadores?
La detección de funciones comprueba si existe una función concreta (if window._blocked_) en lugar de comprobar el tipo de navegador. Es más fiable porque las actualizaciones de los navegadores añaden funciones. La detección de navegador se rompe con las versiones nuevas.
¿Debo ocultar las etiquetas del formulario y apoyarme en los marcadores de posición?
No. Conserva siempre las etiquetas en el HTML. Si el CSS no se carga, el marcador de posición desaparece. Los usuarios y los lectores de pantalla necesitan la etiqueta.
¿Cómo hago que el envío por AJAX funcione con una alternativa tradicional?
Crea un formulario que se envíe a la URL de una acción. Intercepta el envío con JavaScript y usa _blocked_ para enviarlo por AJAX. Si JavaScript falla, el formulario se envía de la forma tradicional. Funcionan ambos caminos.
¿Qué debo probar para asegurarme de que mi formulario es resistente?
Prueba sin JavaScript. Prueba con redes lentas. Prueba con lectores de pantalla. Prueba la navegación solo con teclado. Prueba en navegadores antiguos. Prueba en móvil. Si todo funciona, tu formulario es resistente.

Ponlo en práctica
en tu propia web.

Empieza gratis con WEMASY y crea tu web en pocos minutos.