En muchos formularios el email solo se valida al final, justo cuando la persona ya pulso continuar. Tecnicamente funciona, pero la experiencia llega tarde. Si el dominio parece temporal, si la entrega sera fragil o si la cuenta servira solo para una prueba corta, prefiero dar esa pista antes del submit y hacerlo sin convertir el campo en una alarma constante.
Lo importante, para mi, es separar intencion de castigo. Una persona puede usar un correo valido y aun asi necesitar contexto extra. Baymard lleva tiempo mostrando que la validacion inline ayuda mas cuando orienta la correccion y no solo marca un fallo (Baymard). En registro y onboarding esa diferencia se nota un monton, aunque a veces parezca un detalle menor.
Por que conviene avisar antes del error final
Muchos equipos mezclan tres cosas en una sola etiqueta:
- formato invalido
- riesgo de entrega
- politica de negocio
Cuando eso pasa, el frontend termina diciendo "correo no valido" a casos que en realidad son otra cosa. Un dominio temporal puede ser aceptable para demo, QA o activacion corta. Lo que cambia no es la sintaxis, sino la confianza en la entrega futura o en la recuperacion de cuenta. Si juntas todo, soporte recibe tickets raros y producto pierde una señal util. No es el peor bug del mundo, pero si desgasta bastante.
Ademas, el mensaje final llega tarde. Nielsen Norman Group insiste en que los errores utiles deben ser especificos y accionables (NN/g). Yo extiendo esa idea a las advertencias suaves: si el sistema ya sabe algo util, mejor decirlo con calma antes del bloqueo. No hace falta dramatizarlo, y eso aveces reduce abandono mas de lo esperado.
Un patron sencillo en React para separar intencion y riesgo
Un patron que me funciona bien es calcular un notice ligero mientras la persona escribe y dejar la decision dura para backend. El cliente explica contexto; el servidor conserva la ultima palabra.
import { useId, useState } from "react";
type Notice =
| { kind: "idle"; message: string }
| { kind: "info"; message: string }
| { kind: "warning"; message: string }
| { kind: "error"; message: string };
const TEMP_DOMAINS = new Set(["mailinator.com", "yopmail.com", "tempmail.com"]);
function getNotice(email: string): Notice {
if (!email) {
return {
kind: "idle",
message: "Usa un correo que puedas abrir hoy si vas a terminar el alta."
};
}
if (!email.includes("@") || !email.includes(".")) {
return {
kind: "error",
message: "Revisa el formato del correo antes de continuar."
};
}
const domain = email.split("@")[1]?.toLowerCase() ?? "";
if (TEMP_DOMAINS.has(domain)) {
return {
kind: "warning",
message: "Este dominio puede expirar antes de recibir el enlace de acceso."
};
}
return {
kind: "info",
message: "Te enviaremos un enlace de verificacion a este correo."
};
}
export function EmailField() {
const hintId = useId();
const [email, setEmail] = useState("");
const notice = getNotice(email);
return (
<label>
<span>Correo</span>
<input
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
aria-describedby={hintId}
aria-invalid={notice.kind === "error" || undefined}
/>
<span id={hintId} aria-live="polite">
{notice.message}
</span>
</label>
);
}
Me gusta porque evita dos extremos bastante comunes: no esperar hasta el ultimo segundo y tampoco bloquear demasiado pronto. Si el backend ya trabaja con colas, retries o tiempos de espera, esa precision del frontend encaja bien con lo que hacen otros equipos. Este enfoque conversa bastante bien con ideas como presupuestar emails lentos en FastAPI, donde el sistema gana claridad cuando distingue estados en vez de meter todo en una bolsa.
CSS y accesibilidad para que el aviso no moleste
La UI se rompe menos cuando el espacio del aviso ya existe. Google sigue recomendando evitar cambios inesperados de layout porque empeoran la experiencia percibida y el CLS (web.dev). En este caso no necesitas una capa enorme de diseño, solo una region estable y legible.
.email-hint {
display: block;
min-height: 1.5rem;
margin-top: 0.375rem;
font-size: 0.92rem;
line-height: 1.4;
}
.email-hint[data-kind="idle"],
.email-hint[data-kind="info"] {
color: #5b6470;
}
.email-hint[data-kind="warning"] {
color: #9a4d00;
}
.email-hint[data-kind="error"] {
color: #b42318;
}
Hay tres decisiones pequeñas que suelen salir bien:
- reservar altura para que el boton no salte
- usar
aria-live="polite"para anunciar cambios sin interrumpir - escribir consecuencia y siguiente paso, no solo juicio
Ese tercer punto cambia mucho el tono. "Correo sospechoso" suena medio policial. "Puede expirar antes de recibir el enlace" ayuda a decidir. Es una diferencia simple, pero vuelve el formulario mas humano. Tambien facilita hablar con otros equipos sobre la señal, algo parecido a cuando operaciones documenta senales operativas para correos de guardia: el valor real esta en nombrar bien lo que pasa.
Cuando mostrar una advertencia por correo temporal
No siempre hay que bloquear. Si una persona usa un tempmailso para una demo rapida o una prueba de QA, una advertencia contextual suele bastar. En productos con recuperacion de cuenta, billing o notificaciones criticas, claro, el riesgo sube y el backend puede tomar una decision mas dura. Pero incluso ahi el frontend deberia explicar la razon.
Yo intentaria mostrar la advertencia solo cuando el dominio ya es claro. Antes de eso el mensaje cambia demasiado y el campo se siente nervioso. Tambien conviene registrar esos casos aparte de los fallos de sintaxis. Si en tus eventos terminas mezclando cosas como temp gamil com o tem email con emails realmente malformed, luego leer el funnel se vuelve mas confuso de la cuenta. Es un detalle chico, pero despues nadie recuerda por que la metrica se torcio un poco.
Checklist rapido antes de lanzarlo
- diferencia formato invalido de riesgo contextual
- explica la consecuencia con una frase corta
- mantiene estable el layout cuando cambia el mensaje
- deja la politica final en backend
- registra advertencias y errores por separado
Es un patron pequeño, si, pero quita ruido visual y mejora comprension en un paso muy sensible del producto. A veces no sube una metrica gigante de golpe; mas bien evita pequeñas perdidas de confianza que se acumulan.
Q&A
Debo validar dominios temporales en cada tecla?
No. Esperaria a tener el dominio completo o un estado suficientemente claro. Si no, el aviso parpadea demasiado y queda un poco ansioso.
Esto reemplaza la validacion del servidor?
Para nada. El cliente solo prepara a la persona. La decision final sobre bloqueo, allowlist o riesgo sigue estando mejor en backend.
Vale la pena si el formulario es muy corto?
Si el registro depende de un enlace por email, yo diria que si. Son pocos elementos, pero la claridad ahi evita una friccion muy tonta despues.
Top comments (0)