DEV Community

Silviu Technology
Silviu Technology

Posted on

React: evita CLS en validacion de email

Muchos formularios React validan el email solo cuando ya hay problema visible. El campo arranca limpio, luego aparece un error debajo, despues un hint distinto, luego un icono, y todo el bloque se mueve. Ese rebote visual parece pequeno, pero en signup y checkout se nota muchisimo. La persona esta intentando confirmar si escribio bien su correo, no perseguir mensajes que cambian de sitio.

En equipos frontend esto suele pasar por una razon simple: se piensa mucho en la regex y poco en la estabilidad del estado. Cuando alguien pega algo como dummy e mail o una direccion mal recordada tipo temp gamil com, la interfaz deberia responder con contexto estable. Si el mensaje empuja el boton o desplaza el siguiente campo, la validacion termina sintiendose mas dramatica de lo necesario.

El problema real no es la regex, es el salto visual

Google describe Cumulative Layout Shift como una medida de movimientos inesperados en la pagina. Normalmente lo hablamos en imagenes o ads, pero el mismo principio afecta formularios pequenos: si el area de ayuda aparece tarde y mueve el layout, la tarea se vuelve menos comoda. No siempre vas a romper Core Web Vitals por un solo input, claro, pero si sumas varios campos nerviosos la experiencia queda medio fragil.

Tambien hay un componente de usabilidad. Baymard viene observando desde hace anos que los formularios fallan mas por detalles de feedback que por reglas complejas; cuando el mensaje llega tarde o en el lugar equivocado, la correccion cuesta mas de lo que deberia en sus investigaciones sobre checkout. Ese matiz importa bastante, por que el usuario no separa "accesibilidad", "CSS" y "performance" como nosotros. Solo siente que el form es claro, o no lo es.

Un patron de estado estable para email

El patron que mejor me funciona tiene tres reglas:

  1. la ayuda reserva espacio desde el primer render
  2. el mensaje cambia de contenido, no de posicion
  3. el error fuerte espera a una señal razonable, como blur o submit

Esto hace que la validacion se sienta mas calmada. Primero orientas, luego confirmas, y solo despues corriges. Es la misma idea de reusar estado cuando una accion se repite: si una zona ya existe en la interfaz, reusarla suele ser mejor que insertar otra a ultima hora. Y en flujos de email con varias comprobaciones, esa continuidad se vuelve aun mas util, igual que en estas aprobaciones por email con menos ruido.

Si ademas tu producto deja probar correos temporales para demos o QA, conviene explicar el criterio en texto humano. Un mensaje breve puede decir que aceptas dominios comunes y tambien algunos de prueba, en vez de castigar sin contexto. En ciertos equipos eso evita tickets medio bobos cuando alguien usa un inbox temporal de temp mail so para una smoke test o una demo interna.

Ejemplo en React y CSS

import { useId, useState } from "react";

function looksLikeEmail(value) {
  return /\S+@\S+\.\S+/.test(value);
}

export default function EmailField() {
  const messageId = useId();
  const [value, setValue] = useState("");
  const [touched, setTouched] = useState(false);

  const normalized = value.trim();
  const showError = touched && normalized !== "" && !looksLikeEmail(normalized);

  const message = showError
    ? "Revisa el formato. Usa algo como nombre@dominio.com"
    : "Te enviaremos confirmaciones y cambios importantes a este correo";

  return (
    <label className="emailField">
      <span className="emailLabel">Email</span>
      <input
        type="email"
        value={value}
        onChange={(event) => setValue(event.target.value)}
        onBlur={() => setTouched(true)}
        aria-invalid={showError}
        aria-describedby={messageId}
        autoComplete="email"
      />
      <span
        id={messageId}
        className={showError ? "emailMessage error" : "emailMessage"}
        aria-live="polite"
      >
        {message}
      </span>
    </label>
  );
}
Enter fullscreen mode Exit fullscreen mode
.emailField {
  display: grid;
  gap: 0.375rem;
}

.emailLabel {
  font-weight: 600;
}

.emailMessage {
  min-height: 1.5rem;
  font-size: 0.875rem;
  line-height: 1.4;
  color: #5b6472;
}

.emailMessage.error {
  color: #b42318;
}
Enter fullscreen mode Exit fullscreen mode

Lo importante no es la regex, sinceramente. Lo importante es que min-height reserva el espacio, aria-describedby mantiene la relacion semantica y aria-live="polite" anuncia el cambio sin gritar. En formularios de verdad, esta combinacion evita un monton de micro sacudidas que despues nadie quiere depurar. Es una mejora pequena, pero pega.

Donde se nota la mejora en accesibilidad y conversion

La mejora accesible se ve rapido:

  • la instruccion no desaparece cuando la persona empieza a escribir
  • el lector de pantalla encuentra siempre la misma zona de ayuda
  • el error explica que hacer, no solo que algo fallo

La mejora de producto tambien aparece. Cuando el campo conserva su altura, el boton no baja, el ojo no pierde referencia y el formulario parece mas rapido aunque el JavaScript sea el mismo. Ese tipo de polish suele entrar en la categoria de "detalle menor", pero luego mueve completion rate, sobre todo en movil. No tengo una formula magica aca, pero si he visto que los forms con mensajes estables reciben menos correcciones torpes y menos abandonos raros.

Yo revisaria dos escenarios extra, por si acaso:

  • zoom alto en iOS Safari
  • autocompletado agresivo en Chrome con email guardado

Si en esos casos la ayuda sigue clara y el layout no tiembla, vas por buen camino. Si no, arreglarlo temprano cuesta poco; arreglarlo despues, cuando ya se mezclo con analytics y copys urgentes, es mucho mas molesto.

Preguntas rapidas

Q: ¿Debo validar en cada tecla?

A: Solo si el feedback no interrumpe. Muchas veces blur da una experiencia mas limpia, aunque depende del caso.

Q: ¿Necesito aria-live siempre?

A: No siempre, pero en mensajes que cambian sin mover foco suele ayudar bastante.

Q: ¿Esto sirve si luego hago validacion remota?

A: Si. La capa local ordena la experiencia primero, y la remota entra despues sin meter mas caos.

En React, mejorar un campo de email no exige otra libreria ni un rediseño completo. Exige pensar el estado visual como parte del rendimiento percibido. Cuando el mensaje no mueve nada y la instruccion sigue presente, la validacion deja de sentirse tosca. Y eso, aunque sea sutil, los usuarios lo notan un monton.

Top comments (0)