Contact
Contact form patterns with split layouts, contact information sidebars, and map integration. Accessible and responsive designs for customer communication.
Overview
Contact forms are essential for user communication. These patterns demonstrate various layouts from simple centered forms to complex split designs with contact information and map placeholders.
Key features:
<form-field>for consistent input styling and validation<textarea>with appropriaterowsattribute for message input<layout-sidebar>for split layouts with contact information<icon-wc>for visual contact method indicators- Proper
autocompleteattributes for form autofill - Accessible validation with
<output>andaria-live
Simple Contact Form
A centered contact form using data-layout="cover" for vertical centering. Includes name, email, and message fields with validation support.
<body data-layout="cover" data-layout-min="100vh" data-layout-padding="l"> <layout-card data-layout-max="narrow" data-padding="l" data-layout-principal> <form action="/contact" method="POST" data-layout="stack" data-layout-gap="l"> <header data-layout="stack" data-layout-gap="s"> <h1>Get in touch</h1> <p>We'd love to hear from you. Send us a message and we'll respond as soon as possible.</p> </header> <form-field> <label for="name">Name</label> <input type="text" id="name" name="name" required autocomplete="name" placeholder="Your name" aria-describedby="name-error"/> <output id="name-error" class="error" for="name" aria-live="polite"> Please enter your name. </output> </form-field> <form-field> <label for="email">Email</label> <input type="email" id="email" name="email" required autocomplete="email" placeholder="you@example.com" aria-describedby="email-error"/> <output id="email-error" class="error" for="email" aria-live="polite"> Please enter a valid email address. </output> </form-field> <form-field> <label for="message">Message</label> <textarea id="message" name="message" rows="5" required placeholder="How can we help you?" aria-describedby="message-error"></textarea> <output id="message-error" class="error" for="message" aria-live="polite"> Please enter a message. </output> </form-field> <button type="submit">Send message</button> </form> </layout-card></body>
Split Layout with Contact Info
A two-column layout using <layout-sidebar> with the form as the main content and contact information in the sidebar. Includes address, phone, email, and business hours.
<section class="contact-section"> <layout-cover data-layout-min="100vh" data-layout-padding="xl"> <layout-center data-layout-max="wide"> <layout-sidebar data-layout-gap="2xl" data-layout-sidebar-width="narrow" data-layout-content-min="50"> <!-- Form Panel --> <section class="form-card"> <form action="/contact" method="POST" data-layout="stack" data-layout-gap="l"> <header data-layout="stack" data-layout-gap="s"> <h1>Send us a message</h1> <p>Fill out the form and our team will get back to you within 24 hours.</p> </header> <form-field> <label for="name">Name</label> <input type="text" id="name" name="name" required autocomplete="name" placeholder="Your name"/> </form-field> <form-field> <label for="email">Email</label> <input type="email" id="email" name="email" required autocomplete="email" placeholder="you@example.com"/> </form-field> <form-field> <label for="subject">Subject</label> <input type="text" id="subject" name="subject" required placeholder="What is this regarding?"/> </form-field> <form-field> <label for="message">Message</label> <textarea id="message" name="message" rows="5" required placeholder="Tell us more about your inquiry..."></textarea> </form-field> <button type="submit">Send message</button> </form> </section> <!-- Contact Info Sidebar --> <aside class="contact-info" data-layout="stack" data-layout-gap="xl"> <div data-layout="stack" data-layout-gap="m"> <h3>Contact information</h3> <p>Reach out to us through any of these channels.</p> </div> <div data-layout="stack" data-layout-gap="l"> <div data-layout="cluster" data-layout-gap="m" data-layout-align="start"> <icon-wc name="map-pin"></icon-wc> <div data-layout="stack" data-layout-gap="xs"> <span class="contact-item-label">Address</span> <span class="contact-item-value"> 123 Business Ave, Suite 100<br/> San Francisco, CA 94102 </span> </div> </div> <div data-layout="cluster" data-layout-gap="m" data-layout-align="start"> <icon-wc name="phone"></icon-wc> <div data-layout="stack" data-layout-gap="xs"> <span class="contact-item-label">Phone</span> <span class="contact-item-value"> <a href="tel:+14155551234">(415) 555-1234</a> </span> </div> </div> <div data-layout="cluster" data-layout-gap="m" data-layout-align="start"> <icon-wc name="mail"></icon-wc> <div data-layout="stack" data-layout-gap="xs"> <span class="contact-item-label">Email</span> <span class="contact-item-value"> <a href="mailto:hello@example.com">hello@example.com</a> </span> </div> </div> </div> <div data-layout="stack" data-layout-gap="m"> <h3>Business hours</h3> <div class="hours-list" data-layout="stack" data-layout-gap="xs"> <div data-layout="cluster" data-layout-justify="between"> <span>Monday - Friday</span> <span>9:00 AM - 6:00 PM</span> </div> <div data-layout="cluster" data-layout-justify="between"> <span>Saturday</span> <span>10:00 AM - 4:00 PM</span> </div> <div data-layout="cluster" data-layout-justify="between"> <span>Sunday</span> <span>Closed</span> </div> </div> </div> </aside> </layout-sidebar> </layout-center> </layout-cover></section>
Contact Info Styles
.contact-section { background: var(--color-surface-raised);}.form-card { background: var(--color-surface); border-radius: var(--radius-l); box-shadow: 0 1px 3px oklch(0% 0 0 / 0.1); padding: var(--size-l);}.contact-info h3 { font-size: var(--font-size-lg); margin: 0;}.contact-info icon-wc { color: var(--color-interactive); flex-shrink: 0; margin-top: var(--size-xs);}.contact-item-label { font-weight: var(--font-weight-medium);}.contact-item-value { color: var(--color-text-muted); font-size: var(--font-size-sm);}.hours-list { font-size: var(--font-size-sm); color: var(--color-text-muted);}
With Map
Contact form with a <geo-map> component for displaying your location. Uses a centered header above a split layout with free OpenStreetMap tiles.
<section class="contact-section"> <layout-cover data-layout-min="100vh" data-layout-padding="xl"> <layout-center data-layout-max="wide" data-layout-gap="2xl"> <!-- Header --> <header class="contact-header" data-layout="stack" data-layout-gap="s"> <h1>Contact us</h1> <p>Have questions? We're here to help. Send us a message or visit our office.</p> </header> <!-- Content Grid --> <layout-sidebar data-layout-gap="xl" data-layout-sidebar-width="wide" data-layout-content-min="45"> <!-- Contact Form --> <section class="form-card"> <form action="/contact" method="POST" data-layout="stack" data-layout-gap="l"> <h2>Send a message</h2> <div data-layout="split" data-layout-gap="m"> <form-field> <label for="first-name">First name</label> <input type="text" id="first-name" name="first_name" required autocomplete="given-name" placeholder="John"/> </form-field> <form-field> <label for="last-name">Last name</label> <input type="text" id="last-name" name="last_name" required autocomplete="family-name" placeholder="Doe"/> </form-field> </div> <form-field> <label for="email">Email</label> <input type="email" id="email" name="email" required autocomplete="email" placeholder="john@example.com"/> </form-field> <form-field> <label for="phone">Phone (optional)</label> <input type="tel" id="phone" name="phone" autocomplete="tel" placeholder="(555) 123-4567"/> </form-field> <form-field> <label for="message">Message</label> <textarea id="message" name="message" rows="4" required placeholder="How can we help you?"></textarea> </form-field> <button type="submit">Send message</button> </form> </section> <!-- Map Sidebar --> <aside> <geo-map lat="37.7749" lng="-122.4194" zoom="14" style="--geo-map-height: 100%; min-height: 400px;"> <address> 123 Business Ave, Suite 100<br/> San Francisco, CA 94102 </address> </geo-map> </aside> </layout-sidebar> </layout-center> </layout-cover></section>
Map Styles
.form-card { background: var(--color-surface); border-radius: var(--radius-l); box-shadow: 0 1px 3px oklch(0% 0 0 / 0.1); padding: var(--size-l);}aside geo-map { --geo-map-height: 100%; min-height: 400px;}
Configuration
Key configuration options for contact forms:
| Element/Attribute | Purpose | Options |
|---|---|---|
textarea rows |
Message field height | 4, 5, 6 (adjust to content needs) |
layout-sidebar data-sidebar-width |
Contact info sidebar width | narrow, default, wide |
layout-sidebar data-content-min |
Minimum form width before wrapping | 45, 50, 60 (percentage) |
data-layout="split" |
Side-by-side form fields | Use for first/last name pairs |
autocomplete |
Enable browser autofill | name, email, tel, given-name, family-name |
Usage Notes
- Required fields: Mark essential fields with
requiredattribute;<form-field>adds visual asterisk automatically - Validation messages: Use
<output class="error">witharia-describedbylinking to the input - Success states: Consider showing a success message or redirecting after submission
- Spam prevention: Add honeypot fields or CAPTCHA for production forms
- Map integration: The
<geo-map>component uses free OpenStreetMap tiles — no API key needed - Phone links: Use
tel:protocol for clickable phone numbers on mobile - Email links: Use
mailto:protocol for email addresses - Accessibility: All form fields have labels, icons have appropriate aria attributes
Related
Sign In
Login form patterns with validation
Form Field
Form field element with validation
Layout Sidebar
Sidebar layout for split designs
Icon
Icon component for contact indicators
Geo Map
Map component for location display