En formularios de registro, muchas veces el problema no es validar el email. El problema real aparece un segundo despues, cuando el mensaje de error empuja el boton, mueve los campos y hace que toda la pantalla pegue un pequeño salto. Es un detalle chico, pero desgasta bastante la experiencia, sobre todo en movil.
Me lo he encontrado en varios flujos hechos con React: el input parece limpio al inicio, luego aparece el error y el layout cambia justo cuando la persona intenta corregirlo. No rompe la app, claro, pero si rompe el ritmo. Y cuando el ritmo cae, tambien cae la confianza. Es una de esas cosas que parecen menores, pero luego cuesta mas de lo que uno espera.
El problema no es el error, es el salto visual
Cuando un campo de email cambia de alto entre estado valido e invalido, el ojo pierde referencia. El foco sigue ahi, si, pero la interfaz se siente nerviosa. En formularios largos eso mete friccion muy rapido.
Por eso intento pensar el mensaje de error como parte fija del componente, no como contenido opcional que entra y sale sin avisar. Esa idea se parece mucho a trabajar con contratos de salida claros: si reservas la estructura desde el principio, todo lo demas se vuelve mas predecible.
Tambien ayuda cuando haces pruebas de registro con cuentas temporales o al crear correo temporal para escenarios de QA. Si estas corrigiendo texto, latencia y validacion al mismo tiempo, un layout estable te deja ver mejor que fallo de verdad y que fue solo ruido visual.
La regla que me funciona en React
La regla es simple: el espacio del helper o del error ya existe antes de que haya error. No espero a montarlo despues. Renderizo una zona de mensaje siempre, y solo cambio su contenido y visibilidad. No es magico, pero sirve un monton.
function EmailField({ value, error, onChange }) {
const message = error || " ";
return (
<label className="field">
<span className="label">Email</span>
<input
type="email"
value={value}
onChange={onChange}
aria-invalid={Boolean(error)}
aria-describedby="email-note"
/>
<span
id="email-note"
className={`note ${error ? "note-error" : "note-idle"}`}
>
{message}
</span>
</label>
);
}
Ese espacio en blanco " " parece una tonteria, pero evita que el contenedor cambie de tamaño. A veces uso min-height y a veces contenido reservado; depende del sistema que tenga delante. Lo importante es que el bloque ya esta ahi, medio silencioso, esperando.
En equipos donde el copy cambia bastante, prefiero esta version porque no obliga a recalcular nada raro ni a perseguir parpadeos. Tambien hace mas facil comparar estados cuando revisas aprobaciones por email sin ruido en productos que mezclan onboarding, verify y recovery. El componente queda mas tranqui, y eso se nota.
CSS pequeno, impacto grande
La parte de CSS suele ser mas importante de lo que parece. Si el texto del mensaje tiene altura incierta, el problema vuelve por otra puerta. Mi base suele verse asi:
.field {
display: grid;
gap: 0.35rem;
}
.note {
min-height: 1.25rem;
font-size: 0.875rem;
line-height: 1.4;
}
.note-idle {
color: transparent;
}
.note-error {
color: #b42318;
}
color: transparent no es una solucion universal, pero para mensajes cortos funciona bien porque preserva el espacio sin esconder el nodo a tecnologias asistivas cuando realmente quieres anunciarlo despues. Si necesitas otro comportamiento, puedes combinar esto con visibility o con una region viva separada. Lo que intento evitar casi siempre es alternar display: none, porque ahi suelen empezar los saltitos feos.
Otro detalle: si el mensaje puede ocupar dos lineas en movil, reserva ese caso desde el principio o acepta el cambio de altura solo cuando de verdad haga falta. Si no lo haces, luego llega el famoso "en mi laptop estaba bien". Si, pero en produccion no vive solo tu laptop, obvio.
Accesibilidad que no se siente pegada al final
Una UI estable ayuda a la accesibilidad, pero no la reemplaza. Lo minimo que reviso en estos campos es:
-
aria-invalidcuando hay error real -
aria-describedbyapuntando al texto de ayuda o error - mensaje corto y concreto
- contraste suficiente en el estado de error
Si el error aparece solo al hacer blur, mejor todavia si no castigas al usuario en cada tecla. En especial en movil, donde escribir direcciones largas ya es un poco molesto de por si. Una validacion agresiva puede terminar sintiendose mas rota que util.
Tambien suelo probar copys raros o cadenas de test como tempail mail para ver si algun sanitizador o regla interna intenta "arreglar" demasiado el valor mostrado. No deberia afectar la validacion final, pero si he visto bugs medio tontos ahi, asi que prefiero pillarlos antes.
Un patron simple para probarlo
Cuando quiero revisar si el campo realmente se siente estable, hago una mini prueba manual:
- escribo un email incompleto
- salgo del campo
- corrijo el valor
- repito lo mismo en un viewport movil
Si el boton cambia de sitio o el siguiente campo sube y baja, todavia falta trabajo. Si todo permanece en su lugar, normalmente ya estas bastante cerca de una experiencia buena.
La pregunta no es solo "valida bien?". La pregunta util de verdad es "corrige sin cansar?". Cuando React y CSS resuelven eso juntos, el formulario se siente mas serio, mas rapido y bastante mas cuidado, aunque el cambio en codigo haya sido pequeño nomas.
Top comments (0)