Cómo crear un formulario de contacto en HTML: guía completa
Un formulario de contacto es una de las funcionalidades más comunes en cualquier sitio web. Si su sitio está creado con un generador de sitios estáticos como Astro, Hugo, exportación estática de Next.js o HTML simple, podría pensar que necesita un servidor backend para procesar los envíos del formulario. No lo necesita.
Esta guía explica cómo crear un formulario de contacto HTML completo y listo para producción desde cero, incluido el marcado accesible, la validación del lado del cliente, la protección antispam y la entrega de correo electrónico a través de un endpoint de formulario alojado.
El formulario de contacto HTML básico
Every HTML form needs three things: a <form> element, input fields with name attributes, and a submit button.
<form action="https://api.formsfort.com/submit" method="POST"> <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<label for="name">Name</label> <input type="text" id="name" name="name" required />
<label for="email">Email</label> <input type="email" id="email" name="email" required />
<label for="message">Message</label> <textarea id="message" name="message" rows="5" required></textarea>
<button type="submit">Send message</button></form>The action attribute tells the browser where to send the form data. The method="POST" attribute sends the data as a POST request. Each field needs a name attribute so the backend knows what each value represents.
The hidden access_key field identifies your form to the backend service. Replace YOUR_ACCESS_KEY with the key from your form backend dashboard.
Agregar etiquetas y estructura accesibles
Accessible forms help all users, including those using screen readers. Every input should have a visible <label> associated via the for attribute matching the input id.
Group related fields with <fieldset> and <legend> when appropriate:
<form action="https://api.formsfort.com/submit" method="POST"> <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<fieldset> <legend>Your information</legend>
<label for="name">Full name</label> <input type="text" id="name" name="name" autocomplete="name" required />
<label for="email">Email address</label> <input type="email" id="email" name="email" autocomplete="email" required /> </fieldset>
<label for="message">How can we help?</label> <textarea id="message" name="message" rows="5" maxlength="2000" required></textarea>
<button type="submit">Send message</button></form>The autocomplete attribute helps browsers fill in known values. The maxlength attribute prevents excessively long submissions.
Agregar validación HTML5
HTML5 proporciona atributos de validación integrados que funcionan sin JavaScript:
| Atributo | Propósito |
|---|---|
required | El campo no debe estar vacío |
type="email" | Debe ser un formato de correo electrónico válido |
type="url" | Debe ser una URL válida |
type="tel" | Optimiza el teclado móvil para números de teléfono |
minlength | Recuento mínimo de caracteres |
maxlength | Recuento máximo de caracteres |
pattern | Validación de expresiones regulares personalizada |
min / max | Límites de rango numérico |
Ejemplo con validación:
<label for="email">Work email</label><input type="email" id="email" name="email" required pattern="^[^@\s]+@[^@\s]+\.[^@\s]+$" title="Enter a valid email address"/>
<label for="phone">Phone (optional)</label><input type="tel" id="phone" name="phone" pattern="[0-9\-\+\(\)\s]{7,20}" title="Enter a valid phone number"/>The title attribute provides the validation message shown when the pattern does not match.
Agregar protección antispam con un campo honeypot
Los bots que rastrean la web y completan formularios generalmente llenan todos los campos visibles. Un campo honeypot es una entrada oculta que los usuarios legítimos nunca ven ni completan. Si el campo tiene un valor cuando se envía el formulario, el envío proviene de un bot.
<input type="text" name="botcheck" style="position: absolute; left: -9999px; opacity: 0;" tabindex="-1" autocomplete="off"/>Place this inside your <form> element. Do not use display: none or type="hidden" because sophisticated bots check for those. The CSS positioning approach hides the field visually while keeping it in the DOM.
La mayoría de los servicios backend de formularioss, incluido FormsFort, rechazan automáticamente los envíos donde el campo honeypot tiene un valor.
Agregar un CAPTCHA para una mayor protección antispam
Para formularios con mucho tráfico, agregue un desafío CAPTCHA junto al honeypot. FormsFort admite Turnstile, hCaptcha y reCAPTCHA:
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY"></div><script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>El token de respuesta CAPTCHA se incluye automáticamente en el envío del formulario. El backend de su formulario lo verifica en el lado del servidor antes de procesarlo.
Manejar carga de archivos
To accept file attachments, set the form enctype to multipart/form-data and add a file input:
<form action="https://api.formsfort.com/submit" method="POST" enctype="multipart/form-data"> <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<label for="resume">Upload your resume</label> <input type="file" id="resume" name="resume" accept=".pdf,.doc,.docx" />
<button type="submit">Submit application</button></form>The accept attribute restricts the file picker to specific file types. Your form backend should also validate MIME types and scan files for malware.
Envío a través de AJAX con JavaScript
Para una experiencia de usuario más fluida, envíe el formulario sin recargar la página completa:
<form id="contactForm" action="https://api.formsfort.com/submit" method="POST"> <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" /> <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> <p id="formStatus" aria-live="polite"></p></form>
<script> document.getElementById("contactForm").addEventListener("submit", async (e) => { e.preventDefault(); const form = e.target; const status = document.getElementById("formStatus"); status.textContent = "Sending...";
try { const response = await fetch(form.action, { method: "POST", body: new FormData(form), }); if (response.ok) { status.textContent = "Message sent. We will be in touch."; form.reset(); } else { status.textContent = "Something went wrong. Please try again."; } } catch { status.textContent = "Network error. Please check your connection."; } });</script>The aria-live="polite" attribute ensures screen readers announce the status change.
Redirigir después del envío
To redirect users to a thank-you page after a successful standard (non-AJAX) submission, add a hidden _redirect field:
<input type="hidden" name="_redirect" value="https://example.com/thanks" />Formulario de contacto completo y listo para producción
Aquí hay un formulario de contacto completo que combina todas las técnicas anteriores:
<form action="https://api.formsfort.com/submit" method="POST"> <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" /> <input type="hidden" name="_redirect" value="https://example.com/thanks" /> <input type="hidden" name="_subject" value="New contact form submission" />
<input type="text" name="botcheck" style="position: absolute; left: -9999px; opacity: 0;" tabindex="-1" autocomplete="off" />
<label for="name">Name</label> <input type="text" id="name" name="name" autocomplete="name" required />
<label for="email">Email</label> <input type="email" id="email" name="email" autocomplete="email" required />
<label for="message">Message</label> <textarea id="message" name="message" rows="5" maxlength="2000" required></textarea>
<button type="submit">Send message</button></form>Elegir un backend de formularios
Si aloja un sitio estático, necesita un servicio para recibir y procesar envíos. Las opciones populares incluyen:
| Servicio | Nivel gratuito | Carga de archivos | Webhooks | Google Sheets |
|---|---|---|---|---|
| FormsFort | 100/mo | Sí | Sí | Sí |
| Formspree | 50/mo | Sí | Sí | No |
| Getform | 50/mo | Sí | Sí | No |
| Basin | 100/mo | Sí | Sí | No |
Elija según el volumen de envío, las necesidades de integración y los requisitos de protección antispam.
Resumen
La creación de un formulario de contacto HTML no requiere código de backend. Estructura tu marcado con etiquetas accesibles, agrega atributos de validación HTML5, protégete contra el spam con un campo honeypot y dirige la acción del formulario a un endpoint alojado. El resultado es un formulario listo para producción que funciona en cualquier sitio web estático.
Preguntas frecuentes
¿Puedo crear un formulario de contacto solo con HTML?
Sí. Puede crear el formulario completo con marcado HTML. Para recibir envíos sin un servidor backend, apunte la acción del formulario a un endpoint de formulario alojado como FormsFort, Formspree o Getform.
¿Cómo hago para que mi formulario HTML envíe correos electrónicos?
Agregue un atributo de acción que apunte a un servicio de backend de formularios. El servicio recibe el envío, procesa comprobaciones antispam y entrega los datos por correo electrónico, webhook u hoja de cálculo.
¿Cuál es la mejor manera de prevenir el spam en un formulario de contacto HTML?
Utilice una combinación de un campo de honeypot oculto, un desafío CAPTCHA, limitación de velocidad por IP y restricciones de dominio permitidas. Un campo honeypot detecta la mayoría de los bots sin afectar la experiencia del usuario.
¿Necesito JavaScript para un formulario de contacto HTML?
No. Un formulario HTML estándar con método='POST' y una URL de acción funciona sin JavaScript. Puede agregar JavaScript para el envío AJAX y la validación personalizada, pero no es obligatorio.
¿Cómo agrego carga de archivos a un formulario de contacto HTML?
Establezca el tipo de cifrado del formulario en multiparte/form-data y agregue una entrada con tipo='archivo'. El backend de formularios debe admitir la carga y el escaneo de archivos.
Comience gratis
¿Listo para agregar formularios a su sitio estático?
No se requiere backend. Apunte su formulario HTML a FormsFort y comience a recibir envíos en minutos.