Un formulario de contacto listo para copiar, que se llena rápido en el celular, revisa los datos antes de enviarlos y se puede usar con el teclado y con un lector de pantalla. Todo con HTML y CSS; el envío lo tiene que recibir un programa en tu servidor.
También te puede interesar
El código
<form class="contacto" action="/contacto" method="post">
<h2>Escríbenos</h2>
<label for="c-nombre">Nombre</label>
<input id="c-nombre" name="nombre" autocomplete="name" required>
<label for="c-correo">Correo electrónico</label>
<input id="c-correo" name="correo" type="email" autocomplete="email" required
aria-describedby="c-correo-ayuda">
<small id="c-correo-ayuda">Solo lo usaremos para responderte.</small>
<label for="c-tel">Teléfono <span class="opcional">(opcional)</span></label>
<input id="c-tel" name="telefono" type="tel" autocomplete="tel"
inputmode="tel" pattern="[0-9 +\(\)\-]{8,20}">
<fieldset>
<legend>Motivo</legend>
<label><input type="radio" name="motivo" value="cotizacion" required> Cotización</label>
<label><input type="radio" name="motivo" value="soporte"> Soporte</label>
<label><input type="radio" name="motivo" value="otro"> Otro</label>
</fieldset>
<label for="c-mensaje">Mensaje</label>
<textarea id="c-mensaje" name="mensaje" rows="5" minlength="20" maxlength="2000" required></textarea>
<label class="casilla">
<input type="checkbox" name="aviso" required>
Acepto el <a href="#">aviso de privacidad</a>
</label>
<button>Enviar mensaje</button>
</form>.contacto {
display: grid;
gap: 6px;
max-width: 28rem;
font-family: system-ui, sans-serif;
}
.contacto h2 { margin: 0 0 6px; }
.contacto label { font-weight: 600; margin-top: 8px; }
.contacto input, .contacto textarea, .contacto button { font: inherit; }
.contacto input:not([type=radio], [type=checkbox]), .contacto textarea {
padding: 8px 10px;
border: 2px solid #c9d6e4;
border-radius: 8px;
}
.contacto :focus-visible { outline: 3px solid #1e64af; outline-offset: 1px; }
.contacto :user-invalid { border-color: #b91c1c; background: #fdf2f2; }
.contacto small, .opcional { color: #5b6b7c; font-weight: 400; }
.contacto fieldset { border: 1px solid #c9d6e4; border-radius: 8px; margin-top: 8px; }
.contacto fieldset label, .casilla { font-weight: 400; display: block; margin-top: 4px; }
.contacto button {
margin-top: 12px;
padding: 10px;
border: 0;
border-radius: 8px;
background: #1e64af;
color: white;
font-weight: 700;
cursor: pointer;
}Pulsa «Enviar mensaje» con el formulario vacío y el navegador te llevará al primer campo que falta. Comprobado en los tres navegadores: vacío no se envía, bien lleno sí, y un teléfono con letras no pasa el pattern. El marco del resultado te enseña los datos que se habrían enviado.
Qué hace cada parte
- Cada campo tiene su
labelunido porforeid. El texto de ayuda del correo se une conaria-describedby, y así el lector de pantalla lo lee después de la etiqueta. autocomplete(name,email,tel) deja que el navegador rellene con los datos guardados.type="email"ytype="tel"sacan el teclado adecuado en el celular. El teléfono es opcional, pero si se escribe tiene que cumplir elpattern. Ojo con los paréntesis y el guion dentro de los corchetes: los navegadores actuales leen elpatterncon el modovde las expresiones regulares, que exige escaparlos (\(,\),\-). Sin las barras, la expresión es inválida y el navegador ignora elpatternsin avisar: nos pasó al preparar este ejemplo, y lo detectó la prueba con «abc».- Los botones de opción comparten
namey van en unfieldsetcon sulegend; con ponerrequireden uno, el grupo entero es obligatorio. :user-invalidmarca en rojo los campos mal llenados solo después de tocarlos, no al abrir la página.method="post": el mensaje no debe quedar en la dirección ni en el historial.
Cada fragmento de HTML de esta página pasó por el Nu Html Checker 26.11.4 (el validador del W3C) y cada resultado se pintó y se midió en Chromium, Firefox y WebKit antes de publicarla. Prueba tus cambios en el editor de HTML y CSS o aprende desde cero con el curso.