<header> <nav> <a href="#">Home</a> <a href="#">Work</a> <a href="#">Contact</a> </nav> </header> <main class="contact-wrapper"> <h1>Get in touch</h1> <p class="intro"> Have a question, collaboration idea, or need support? Fill out the form below and I'll get back to you as soon as possible. </p> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" required> <label>Email:</label> <input type="email" name="email" required> <label>Subject:</label> <input type="text" name="subject" required> <label>Message:</label> <textarea name="message" rows="5" required></textarea> <button type="submit">Send Message</button> </form> </main>
/* Centered narrow column, Apple-style typography */ .contact-wrapper { max-width: 880px; margin: 0 auto; padding: 80px 20px; } h1 { font-size: 32px; font-weight: 600; letter-spacing: -0.015em; } .intro { max-width: 580px; color: #555; margin-bottom: 48px; } form { display: flex; flex-direction: column; gap: 18px; max-width: 540px; } input, textarea { padding: 12px 14px; border-radius: 8px; border: 1px solid #e5e5e5; } button[type="submit"] { width: 180px; padding: 12px 18px; border-radius: 999px; border: 1px solid #111; background: transparent; cursor: pointer; } button:hover { background: #111; color: #fff; }
Get in touch
Have a question, collaboration idea, or need support? Fill out the form below and I'll get back to you as soon as possible.
<section class="hero"> <div> <h1>Let's Work Together</h1> <p>Curious about collaboration, design work, development, or speaking engagements? Reach out and I'll respond shortly.</p> </div> </section> <main class="contact-wrapper"> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Subject:</label> <input type="text" name="subject" placeholder="Subject" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="Your Message" required></textarea> <button type="submit">Send Message</button> </form> </main>
/* Full-width hero image with bottom-aligned text */ .hero { width: 100%; min-height: 45vh; background: url("image.jpg") center/cover no-repeat; display: flex; align-items: flex-end; justify-content: center; padding: 100px 20px 40px; text-align: center; } .hero h1 { font-size: 42px; font-weight: 600; letter-spacing: -0.025em; } .hero p { max-width: 600px; color: #555; font-size: 18px; }
Let's Work Together
Curious about collaboration, design work, development, or speaking engagements? Reach out and I'll respond shortly.
<body> <header> <nav> <a href="#">Home</a> <a href="#">Contact</a> </nav> </header> <main class="wrapper"> <h1>Contact</h1> <p class="intro"> Questions, collaborations, project requests — reach out anytime. </p> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Subject:</label> <input type="text" name="subject" placeholder="Subject" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="Your Message" required></textarea> <button type="submit">Send Message</button> </form> </main> </body>
/* Custom properties for a dark palette */ :root { --d-gray: #0c0c0c; --gray: #2a2a2a; --light-gray: #4a4a4a; --white: #eaeaea; } body { background: var(--d-gray); color: var(--white); } input, textarea { background: var(--gray); border: 1px solid #000; color: var(--white); } button[type="submit"] { border: 1px solid var(--white); color: var(--white); background: transparent; } button:hover { background: var(--white); color: #000; }
Contact
Questions, collaborations, project requests—reach out anytime.
<section class="split"> <div class="left-img"></div> <div class="right-form"> <h1>Let's Connect</h1> <p>I'd love to hear from you. Send a message and I'll respond soon.</p> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Subject:</label> <input type="text" name="subject" placeholder="Subject" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="Your Message" required></textarea> <button type="submit">Send Message</button> </form> </div> </section>
/* Flexbox 50/50 split, stacks on mobile */ .split { display: flex; min-height: 100vh; flex-wrap: wrap; } .left-img { flex: 1; min-width: 300px; background: url("image.jpg") center/cover no-repeat; } .right-form { flex: 1; min-width: 300px; padding: 70px 40px; display: flex; flex-direction: column; justify-content: center; } /* Stack into a single column below 850px */ @media (max-width: 850px) { .split { flex-direction: column; } }
Let's Connect
I'd love to hear from you. Send a message and I'll respond soon.
<main class="wrapper"> <h1>Contact Support</h1> <p class="sub">Send a message or find answers using the resources below.</p> <div class="grid"> <div class="panel"> <strong>Resources</strong> FAQs<br>Documentation<br>Service Status </div> <div> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Subject:</label> <input type="text" name="subject" placeholder="Subject" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="Your Message" required></textarea> <button type="submit">Send Message</button> </form> </div> <div class="panel"> <strong>Contact Info</strong> Email: support@example.com<br> Office Hours: M–F<br>9 AM–5 PM </div> </div> </main>
/* 3-column grid: narrow - wide - narrow */ .grid { display: grid; grid-template-columns: 1fr 2fr 1fr; gap: 30px; } .panel { padding: 10px 0; font-size: 15px; color: #666; } .panel strong { color: #111; display: block; margin-bottom: 8px; } /* Collapse to single column on small screens */ @media (max-width: 900px) { .grid { grid-template-columns: 1fr; } }
Contact Support
Send a message or find answers using the resources below.
Documentation
Service Status
Office Hours: M–F
9 AM–5 PM
<section class="grad-hero"> <h1>Reach Out</h1> <p>Send questions, ideas, or project inquiries. Let's create something extraordinary.</p> </section> <main class="wrapper"> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Subject:</label> <input type="text" name="subject" placeholder="Subject" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="Your Message" required></textarea> <button type="submit">Send Message</button> </form> </main>
/* Layered radial gradients create a colorful glow */ .grad-hero { padding: 120px 20px 80px; text-align: center; background: radial-gradient(circle at 20% 20%, rgba(255,107,157,.35), transparent 55%), radial-gradient(circle at 80% 30%, rgba(108,99,255,.35), transparent 55%), radial-gradient(circle at 50% 90%, rgba(95,211,255,.35), transparent 55%), linear-gradient(135deg, #fef6fb 0%, #f0efff 50%, #eefaff 100%); } /* Gradient-filled text using background-clip */ .grad-hero h1 { font-size: 48px; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, #e55481, #6c63ff 60%, #00a9e0); -webkit-background-clip: text; background-clip: text; color: transparent; } .grad-hero p { color: #555; max-width: 600px; margin: 0 auto; font-size: 18px; }
Reach Out
Send questions, ideas, or project inquiries. Let's create something extraordinary.
<main class="wrap"> <h1>Get in Touch</h1> <p>Pick whichever channel works best — we reply within 24 hours.</p> <div class="contact-grid"> <div class="contact-card"> <span>✉️</span> <h3>Email</h3> <a href="mailto:hi@site.com">hi@site.com</a> </div> <div class="contact-card"> <span>📞</span> <h3>Phone</h3> <a href="tel:+15551234567">(555) 123-4567</a> </div> <div class="contact-card"> <span>💬</span> <h3>Live Chat</h3> <p>M–F 9am–5pm EST</p> </div> <div class="contact-card"> <span>📍</span> <h3>Visit</h3> <p>123 Main St, VA</p> </div> </div> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="How can we help?" required></textarea> <button type="submit">Send Message</button> </form> </main>
/* Responsive auto-fit grid of contact cards */ .contact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; margin-bottom: 50px; } .contact-card { background: #f7f7f8; border: 1px solid #eee; border-radius: 12px; padding: 24px; text-align: center; transition: all 0.2s; } .contact-card:hover { background: #fff; box-shadow: 0 6px 18px rgba(0,0,0,.06); transform: translateY(-2px); } .contact-card .emoji { font-size: 2rem; display: block; margin-bottom: 10px; }
Get in Touch
Pick whichever channel works best — we reply within 24 hours.
<main class="wrap"> <h1>We're here to help</h1> <p>Check the FAQ first — or send us a message and we'll reply within 24 hours.</p> <div class="two-col"> <section class="faq"> <h3>Frequent Questions</h3> <div class="faq-item"> <div class="faq-q">How fast do you respond?</div> <div class="faq-a"> We reply to all messages within 24 hours on business days (M–F). </div> </div> <div class="faq-item"> <div class="faq-q">Where can I find pricing?</div> <div class="faq-a"> Visit our pricing page for a full breakdown of plans and features. </div> </div> <div class="faq-item"> <div class="faq-q">Do you offer student discounts?</div> <div class="faq-a"> Yes — email us with a .edu address for 50% off. </div> </div> <div class="faq-item"> <div class="faq-q">Can I schedule a demo?</div> <div class="faq-a"> Absolutely. Use the form and mention "demo" in the subject. </div> </div> </section> <section> <form action="https://formspree.io/f/YOUR_ID" method="POST"> <label>Name:</label> <input type="text" name="name" placeholder="Your Name" required> <label>Email:</label> <input type="email" name="email" placeholder="Your Email" required> <label>Subject:</label> <input type="text" name="subject" placeholder="Subject" required> <label>Message:</label> <textarea name="message" rows="5" placeholder="Your Message" required></textarea> <button type="submit">Send Message</button> </form> </section> </div> </main>
/* Two-column layout: FAQ | form */ .two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 50px; } /* FAQ accordion — toggled with .open class */ .faq-item { padding: 14px 0; border-bottom: 1px solid #f0f0f0; cursor: pointer; } .faq-q { font-weight: 500; display: flex; justify-content: space-between; } .faq-q::after { content: "+"; color: #999; } .faq-item.open .faq-q::after { content: "−"; } .faq-a { display: none; padding-top: 10px; } .faq-item.open .faq-a { display: block; } @media (max-width: 800px) { .two-col { grid-template-columns: 1fr; } }
We're here to help
Check the FAQ first — or send us a message and we'll reply within 24 hours.
Frequent Questions
<!-- placeholder=" " (a space) makes the float trick work --> <form class="contact" novalidate> <div class="float-field"> <input type="text" id="name" placeholder=" "> <label for="name">Your name</label> <div class="err">Please enter your name.</div> </div> <div class="float-field"> <input type="email" id="email" placeholder=" "> <label for="email">Email address</label> <div class="err">Please enter a valid email.</div> </div> <div class="float-field"> <textarea id="msg" placeholder=" "></textarea> <label for="msg">Message</label> <div class="err">Please write a short message.</div> </div> <button type="submit">Send Message</button> </form> <div class="form-success">Thanks! Your message has been sent — we'll be in touch soon.</div>
/* Label sits inside, floats up on focus or when filled */ .float-field { position: relative; } .float-field label { position: absolute; left: 11px; top: 14px; background: #fff; padding: 0 5px; color: #999; transition: all .16s ease; } .float-field input:focus + label, .float-field input:not(:placeholder-shown) + label { top: -8px; font-size: 12px; color: #111; } /* Error state — toggled by JS */ .err { display: none; color: #e0245e; font-size: 12px; } .float-field.invalid input { border-color: #e0245e; } .float-field.invalid .err { display: block; }
// Validate on submit, show errors inline, then a success message
const form = document.querySelector('.contact');
form.addEventListener('submit', (e) => {
e.preventDefault();
let ok = true;
form.querySelectorAll('.float-field').forEach((field) => {
const input = field.querySelector('input, textarea');
const valid = input.type === 'email'
? /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(input.value)
: input.value.trim() !== '';
field.classList.toggle('invalid', !valid);
if (!valid) ok = false;
});
if (ok) {
form.style.display = 'none';
document.querySelector('.form-success').style.display = 'flex';
}
});Send a message
The label sits inside the field, then floats up when you type. Errors appear inline, and the success note shows right here — no page reload.
<!-- The value to copy lives in data-copy --> <div class="copy-row" data-copy="hello@studio.com"> <span class="copy-ic">✉</span> <div class="copy-meta"> <div class="lbl">Email</div> <div class="val">hello@studio.com</div> </div> <span class="copy-hint">Click to copy</span> </div> <div class="copy-row" data-copy="+1 (703) 555-0142"> <span class="copy-ic">☎</span> <div class="copy-meta"> <div class="lbl">Phone</div> <div class="val">+1 (703) 555-0142</div> </div> <span class="copy-hint">Click to copy</span> </div> <div class="copy-row" data-copy="123 Web St, Annandale, VA"> <span class="copy-ic">📍</span> <div class="copy-meta"> <div class="lbl">Address</div> <div class="val">123 Web St, Annandale, VA</div> </div> <span class="copy-hint">Click to copy</span> </div> <div class="socials"> <a href="#" aria-label="GitHub">GitHub</a> <a href="#" aria-label="LinkedIn">LinkedIn</a> <a href="#" aria-label="Instagram">Instagram</a> </div>
.copy-row { display: flex; align-items: center; gap: 16px; padding: 16px 18px; border: 1px solid #e5e5e5; border-radius: 14px; cursor: pointer; transition: all .18s; } .copy-row:hover { border-color: #111; transform: translateY(-2px); } /* .copied class is added by JS after a successful copy */ .copy-row.copied { border-color: #1a7f43; } .copy-row.copied .copy-hint { color: #1a7f43; font-weight: 600; }
// Copy the data-copy value, then show "Copied!" for 1.5s
document.querySelectorAll('.copy-row').forEach((row) => {
row.addEventListener('click', () => {
navigator.clipboard.writeText(row.dataset.copy).then(() => {
const hint = row.querySelector('.copy-hint');
const original = hint.textContent;
row.classList.add('copied');
hint.textContent = 'Copied!';
setTimeout(() => {
row.classList.remove('copied');
hint.textContent = original;
}, 1500);
});
});
});Reach us directly
Tap any detail below to copy it to your clipboard.
<div class="split"> <div class="map-side"> <!-- Free Google Maps embed: ?q=PLACE&output=embed --> <iframe src="https://www.google.com/maps?q=Annandale,VA&output=embed" title="Map" loading="lazy"></iframe> </div> <div class="form-side"> <h2>Visit or write</h2> <p class="intro">Find us on the map, or drop a message and we'll reply within a day.</p> <form action="#" method="POST"> <input type="text" placeholder="Your name" required> <input type="email" placeholder="Your email" required> <textarea rows="4" placeholder="Your message" required></textarea> <button type="submit">Send</button> </form> </div> </div>
/* Two equal columns; map fills its side */ .split { display: grid; grid-template-columns: 1fr 1fr; min-height: 520px; } .map-side { position: relative; } .map-side iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; } .form-side { padding: 56px 48px; } /* Stack on small screens */ @media (max-width: 800px) { .split { grid-template-columns: 1fr; } }
Visit or write
Find us on the map, or drop a message and we'll reply within a day.
<form> <label for="name">Name</label> <input type="text" id="name" placeholder="Your name"> <label for="msg">Message</label> <textarea id="msg" maxlength="300" placeholder="Up to 300 characters"></textarea> <div class="count-row"><span class="counter"><b id="count">0</b>/300</span></div> <button class="send-btn"> <span class="btn-label">Send Message</span> <span class="spinner"></span> <span class="check">✓</span> </button> </form>
/* Button swaps label → spinner → check via classes */ .spinner { width: 18px; height: 18px; display: none; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; border-radius: 50%; animation: spin .7s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .send-btn.loading .btn-label { display: none; } .send-btn.loading .spinner { display: block; } .send-btn.done { background: #1a7f43; } .counter.warn { color: #e0245e; }
// Live counter + animated button (loading → done)
const msg = document.getElementById('msg');
const count = document.getElementById('count');
msg.addEventListener('input', () => {
count.textContent = msg.value.length;
count.parentElement.classList.toggle('warn', msg.value.length > 280);
});
document.querySelector('.send-btn').addEventListener('click', (e) => {
e.preventDefault();
const btn = e.currentTarget;
btn.classList.add('loading');
setTimeout(() => {
btn.classList.remove('loading');
btn.classList.add('done');
}, 1400);
});Say hello
Watch the button animate on send, and the counter update live as you type.
Live preview
Complete HTML — copy this whole file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contact Us</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
background: #f5f5f7; color: #111; line-height: 1.55;
}
/* ===== Top nav ===== */
.site-header {
display: flex; align-items: center; justify-content: space-between;
padding: 16px 40px; background: #fff; border-bottom: 1px solid #e5e5e5;
}
.site-header .logo { font-weight: 700; font-size: 1.1rem; text-decoration: none; color: #111; }
.site-header nav { display: flex; gap: 28px; }
.site-header nav a { text-decoration: none; color: #555; font-size: 15px; }
.site-header nav a:hover { color: #111; }
/* ===== Gradient hero ===== */
.grad-hero {
padding: 90px 20px 70px; text-align: center;
background:
radial-gradient(circle at 20% 20%, rgba(255, 107, 157, 0.35), transparent 55%),
radial-gradient(circle at 80% 30%, rgba(108, 99, 255, 0.35), transparent 55%),
radial-gradient(circle at 50% 90%, rgba(95, 211, 255, 0.35), transparent 55%),
linear-gradient(135deg, #fef6fb 0%, #f0efff 50%, #eefaff 100%);
}
.grad-hero h1 {
font-size: 44px; font-weight: 700; margin-bottom: 14px; letter-spacing: -0.02em;
background: linear-gradient(135deg, #e55481, #6c63ff 60%, #00a9e0);
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.grad-hero p { color: #555; max-width: 560px; margin: 0 auto; font-size: 18px; }
/* ===== Layout wrapper ===== */
.wrap { max-width: 1000px; margin: 0 auto; padding: 60px 20px; }
/* ===== Multi-contact cards ===== */
.contact-grid {
display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px; margin-bottom: 60px;
}
.contact-card {
background: #fff; border: 1px solid #eee; border-radius: 12px;
padding: 24px; text-align: center; transition: all 0.2s;
}
.contact-card:hover {
box-shadow: 0 6px 18px rgba(0,0,0,0.06); transform: translateY(-2px);
}
.contact-card .emoji {
font-size: 1.6rem; display: inline-flex; width: 56px; height: 56px;
align-items: center; justify-content: center;
background: linear-gradient(135deg, #e55481, #bf5af2); color: #fff;
border-radius: 14px; margin-bottom: 14px;
}
.contact-card h3 { font-size: 1rem; margin-bottom: 6px; }
.contact-card p { font-size: 0.9rem; color: #666; }
.contact-card a { color: #111; text-decoration: none; font-weight: 500; }
.contact-card a:hover { text-decoration: underline; }
/* ===== Form card with floating labels ===== */
.form-card {
max-width: 560px; margin: 0 auto; background: #fff;
border: 1px solid #e5e5e5; border-radius: 16px;
padding: 40px 36px; box-shadow: 0 4px 18px rgba(0,0,0,0.05);
}
.form-card h2 { font-size: 28px; font-weight: 600; margin-bottom: 8px; letter-spacing: -0.015em; }
.form-card .intro { color: #555; margin-bottom: 34px; }
.float-field { position: relative; margin-bottom: 26px; }
.float-field input, .float-field textarea {
width: 100%; padding: 18px 14px 7px; font-size: 15px; font-family: inherit;
border: 1px solid #d1d1d6; border-radius: 10px; background: #fff;
}
.float-field textarea { min-height: 120px; resize: vertical; }
.float-field label {
position: absolute; left: 11px; top: 14px; color: #999; font-size: 15px;
pointer-events: none; background: #fff; padding: 0 5px; transition: all .16s ease;
}
.float-field input:focus + label,
.float-field input:not(:placeholder-shown) + label,
.float-field textarea:focus + label,
.float-field textarea:not(:placeholder-shown) + label {
top: -8px; font-size: 12px; color: #111; font-weight: 500;
}
.float-field input:focus, .float-field textarea:focus { outline: none; border-color: #111; }
.float-field.invalid input, .float-field.invalid textarea { border-color: #e0245e; }
.float-field.invalid label { color: #e0245e; }
.err { color: #e0245e; font-size: 12.5px; margin-top: 6px; display: none; }
.float-field.invalid .err { display: block; }
.count-row { display: flex; justify-content: flex-end; margin: -18px 0 22px; }
.counter { font-size: 12.5px; color: #999; }
.counter.warn { color: #e0245e; }
.send-btn {
position: relative; width: 200px; height: 48px; border: none; border-radius: 999px;
background: #111; color: #fff; font-size: 15px; cursor: pointer; overflow: hidden;
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.send-btn:hover { opacity: .9; }
.send-btn .spinner {
width: 18px; height: 18px; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff;
border-radius: 50%; display: none; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.send-btn.loading .btn-label { display: none; }
.send-btn.loading .spinner { display: block; }
.send-btn.done { background: #1a7f43; }
.send-btn.done .btn-label, .send-btn.done .spinner { display: none; }
.send-btn .check { display: none; }
.send-btn.done .check { display: inline; }
.form-success {
display: none; align-items: center; gap: 12px;
background: #e8f7ee; border: 1px solid #b6e3c6; color: #1a7f43;
padding: 18px 20px; border-radius: 12px; font-size: 15px; font-weight: 500;
}
.form-card.show-success #contactForm { display: none; }
.form-card.show-success .form-success { display: flex; }
@media (max-width: 600px) {
.site-header { padding: 14px 20px; }
.grad-hero h1 { font-size: 34px; }
.form-card { padding: 30px 22px; }
}
</style>
</head>
<body>
<header class="site-header">
<a href="#" class="logo">Studio</a>
<nav>
<a href="#">Home</a>
<a href="#">Work</a>
<a href="#">Contact</a>
</nav>
</header>
<section class="grad-hero">
<h1>Get in touch</h1>
<p>Have a question, a project idea, or just want to say hello? Pick a method below or send us a message — we reply within 24 hours.</p>
</section>
<main class="wrap">
<!-- Multiple contact methods -->
<div class="contact-grid">
<div class="contact-card">
<div class="emoji">✉</div>
<h3>Email</h3>
<p><a href="mailto:hello@studio.com">hello@studio.com</a></p>
</div>
<div class="contact-card">
<div class="emoji">☎</div>
<h3>Phone</h3>
<p><a href="tel:+15551234567">(555) 123-4567</a></p>
</div>
<div class="contact-card">
<div class="emoji">📍</div>
<h3>Visit</h3>
<p>123 Main St, Annandale, VA</p>
</div>
<div class="contact-card">
<div class="emoji">🕑</div>
<h3>Hours</h3>
<p>Mon–Fri, 9am–5pm ET</p>
</div>
</div>
<!-- Form with floating labels, validation, live counter, animated button -->
<div class="form-card" id="formCard">
<h2>Send a message</h2>
<p class="intro">Fill out the short form below and we’ll get back to you as soon as we can.</p>
<form id="contactForm" novalidate>
<div class="float-field">
<input type="text" id="name" name="name" placeholder=" ">
<label for="name">Your name</label>
<div class="err">Please enter your name.</div>
</div>
<div class="float-field">
<input type="email" id="email" name="email" placeholder=" ">
<label for="email">Email address</label>
<div class="err">Please enter a valid email.</div>
</div>
<div class="float-field">
<textarea id="message" name="message" maxlength="300" placeholder=" "></textarea>
<label for="message">Your message</label>
<div class="err">Please write a short message.</div>
</div>
<div class="count-row"><span class="counter"><b id="count">0</b>/300</span></div>
<button type="submit" class="send-btn">
<span class="btn-label">Send Message</span>
<span class="spinner"></span>
<span class="check">✓ Sent</span>
</button>
</form>
<div class="form-success">
<span>✓</span>
<span>Thanks! Your message is on its way — we’ll reply within 24 hours.</span>
</div>
</div>
</main>
<script>
var form = document.getElementById('contactForm');
var card = document.getElementById('formCard');
var msg = document.getElementById('message');
var count = document.getElementById('count');
var btn = form.querySelector('.send-btn');
// Live character counter
msg.addEventListener('input', function () {
count.textContent = msg.value.length;
count.parentElement.classList.toggle('warn', msg.value.length > 280);
});
// Validate, animate button, then show success
form.addEventListener('submit', function (e) {
e.preventDefault();
var ok = true;
form.querySelectorAll('.float-field').forEach(function (field) {
var input = field.querySelector('input, textarea');
var valid = input.type === 'email'
? /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(input.value)
: input.value.trim() !== '';
field.classList.toggle('invalid', !valid);
if (!valid) ok = false;
});
if (!ok) return;
btn.classList.add('loading');
setTimeout(function () {
btn.classList.remove('loading');
btn.classList.add('done');
setTimeout(function () { card.classList.add('show-success'); }, 500);
}, 1300);
});
</script>
</body>
</html>