Contact form popup
A dialog that opens over the page instead of taking you to a contact page. It uses the native <dialog> element, so Escape closes it and focus is trapped without a line of code from you; Alpine only carries the sending state. Tailwind and Alpine both come from a CDN so the file runs as-is. If your site already builds Tailwind, drop the CDN script and keep the markup.
TailwindCSS · Alpine.js · HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Popup contact form</title>
<script src="https://cdn.tailwindcss.com"></script>
<script defer src="https://unpkg.com/alpinejs@3/dist/cdn.min.js"></script>
<style>
body { margin: 0; }
</style>
</head>
<body>
<main class="min-h-screen grid place-items-center p-6 bg-zinc-100">
<div class="text-center">
<h1 class="text-xl font-semibold text-zinc-900">Your page carries on behind this.</h1>
<p class="mt-1 text-sm text-zinc-500">The form opens over it instead of navigating away.</p>
<button
onclick="document.getElementById('contact').showModal()"
class="mt-6 rounded-lg bg-zinc-900 px-4 py-2.5 text-sm font-medium text-white transition active:scale-[0.98] hover:bg-zinc-700"
>
Contact us
</button>
</div>
</main>
<!-- Native dialog: Escape, focus trapping and the backdrop are free. -->
<dialog id="contact" class="w-[min(28rem,calc(100vw-2rem))] rounded-xl border border-zinc-200 p-0 backdrop:bg-zinc-900/40">
<form
method="POST"
action="https://app.portform.co/api/submit"
class="p-6"
x-data="{ sending: false }"
@submit="sending = true"
>
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input type="checkbox" name="botcheck" class="hp" tabindex="-1" autocomplete="off" />
<div class="flex items-start justify-between gap-4">
<div>
<h2 class="text-lg font-semibold text-zinc-900">Get in touch</h2>
<p class="mt-0.5 text-sm text-zinc-500">We usually reply the same day.</p>
</div>
<button
type="button"
onclick="document.getElementById('contact').close()"
class="-m-1 rounded p-1 text-zinc-400 hover:text-zinc-900"
aria-label="Close"
>×</button>
</div>
<div class="mt-5 space-y-3">
<input type="text" name="name" autocomplete="name" placeholder="Your name" required
class="w-full rounded-lg border border-zinc-300 px-3 py-2 text-sm outline-none focus:border-transparent focus:outline-2 focus:outline-zinc-900" />
<input type="email" name="email" autocomplete="email" placeholder="you@example.com" required
class="w-full rounded-lg border border-zinc-300 px-3 py-2 text-sm outline-none focus:border-transparent focus:outline-2 focus:outline-zinc-900" />
<textarea name="message" rows="4" placeholder="How can we help?" required
class="w-full rounded-lg border border-zinc-300 px-3 py-2 text-sm outline-none focus:border-transparent focus:outline-2 focus:outline-zinc-900"></textarea>
</div>
<button
type="submit"
:disabled="sending"
class="mt-4 w-full rounded-lg bg-zinc-900 px-4 py-2.5 text-sm font-medium text-white transition active:scale-[0.98] hover:bg-zinc-700 disabled:opacity-60"
x-text="sending ? 'Sending…' : 'Send message'"
>Send message</button>
</form>
</dialog>
</body>
</html>Replace YOUR_ACCESS_KEY with the access key from your dashboard. Create one free. The endpoint and the honeypot are already in place.
Useful for
- Feedback formsLet customers tell you what to fix, straight to your inbox.
- Customer supportA support form that reaches your team fast.
The part behind every one of these is a form backend. This template posts to a PortForm form endpoint, which stores each submission and sends it to your email; the docs cover the fields and responses.
Other templates
- Basic HTML contact formHTML · CSS
- Ajax contact formHTML · CSS · JavaScript
- JavaScript form validationHTML · CSS · JavaScript
- Multi-column contact formHTML · CSS
- Masked phone inputHTML · CSS · JavaScript
- Contact form with dark modeHTML · CSS
- Raw contact form (no CSS)HTML
- Multi-step NPS surveyHTML · CSS · JavaScript
- Multi-step survey formVue · HTML · CSS
- Popover feedback widgetTailwindCSS · Alpine.js · HTML
- File upload formHTML · CSS
- JavaScript file upload formHTML · CSS · JavaScript
- React contact formReact · HTML · CSS