Basic Form
Accessible form pattern using the form-field custom element. Native HTML5 validation with CSS-only feedback states.
Overview
This snippet provides a complete contact form with all common input types. It uses form.stacked for vertical layout, <form-field> for validated inputs, and semantic elements like <fieldset> and <footer> instead of wrapper divs.
Key features:
- Zero wrapper
<div>tags — every element is semantic or custom - Native HTML5 validation (no JavaScript required)
- Accessible labels and helper text
- Consistent field styling via
<form-field> - Proper autocomplete attributes
- Checkbox and radio group patterns
- Form actions via
footer.actions.end
Live Example
A contact form with text inputs, select, textarea, checkbox, and radio buttons.
Source Code
The form.stacked class provides vertical layout. Each validated field uses <form-field>; optional controls use bare semantic elements.
<form action="/submit" method="POST" class="stacked"> <h2>Contact Form</h2> <!-- Text input with required validation --> <form-field> <label for="name">Full Name</label> <input type="text" id="name" name="name" required autocomplete="name" placeholder="John Doe" aria-describedby="name-msg" > <output id="name-msg" for="name" aria-live="polite"> Enter your full name as it appears on official documents. </output> </form-field> <!-- Email input with type validation --> <form-field> <label for="email">Email Address</label> <input type="email" id="email" name="email" required autocomplete="email" placeholder="john@example.com" aria-describedby="email-msg" > <output id="email-msg" for="email" aria-live="polite"> We'll never share your email with anyone else. </output> </form-field> <!-- Select dropdown --> <form-field> <label for="subject">Subject</label> <select id="subject" name="subject" required> <option value="">Select a topic...</option> <option value="general">General Inquiry</option> <option value="support">Technical Support</option> <option value="sales">Sales Question</option> <option value="feedback">Feedback</option> </select> </form-field> <!-- Textarea with minlength --> <form-field> <label for="message">Message</label> <textarea id="message" name="message" rows="5" required minlength="20" placeholder="Tell us what's on your mind..." aria-describedby="message-msg" ></textarea> <output id="message-msg" for="message" aria-live="polite"> Minimum 20 characters. </output> </form-field> <!-- Optional checkbox — no form-field needed --> <label> <input type="checkbox" name="newsletter" value="yes"> Subscribe to our newsletter </label> <!-- Radio group — fieldset.minimal.group replaces inner div --> <fieldset class="minimal group"> <legend>Preferred contact method</legend> <label> <input type="radio" name="contact-method" value="email" checked> Email </label> <label> <input type="radio" name="contact-method" value="phone"> Phone </label> </fieldset> <!-- Form actions — semantic footer replaces div --> <footer class="actions end"> <button type="reset" class="secondary">Reset</button> <button type="submit">Send Message</button> </footer></form>
Field Types
Text Input
Standard text input with label, placeholder, and helper text.
<form-field> <label for="name">Full Name</label> <input type="text" id="name" name="name" required aria-describedby="name-msg"> <output id="name-msg" for="name" aria-live="polite">Helper text goes here.</output></form-field>
Select Dropdown
Native select with placeholder option.
<form-field> <label for="subject">Subject</label> <select id="subject" name="subject" required> <option value="">Select a topic...</option> <option value="general">General Inquiry</option> </select></form-field>
Checkbox
Optional checkbox — bare <label> is sufficient when no validation or helper text is needed.
<label> <input type="checkbox" name="newsletter" value="yes"> Subscribe to our newsletter</label>
Radio Group
Radio buttons grouped in a fieldset.minimal.group — removes border/padding and stacks children with flex column. No inner <div> needed.
<fieldset class="minimal group"> <legend>Preferred contact method</legend> <label> <input type="radio" name="contact-method" value="email" checked> Email </label> <label> <input type="radio" name="contact-method" value="phone"> Phone </label></fieldset>
Usage Notes
- Labels: Every input must have an associated label with matching
for/idattributes - Autocomplete: Use appropriate
autocompletevalues to help browsers autofill - Validation: Use native attributes like
required,minlength,pattern, andtype - Helper text: Use
<output>witharia-describedbyandaria-live="polite"for accessible hints - Grouping: Use
<fieldset>and<legend>for radio/checkbox groups - Actions: Use
footer.actions.endfor right-aligned submit/reset buttons
Related
Form Field
Form field element documentation
Input Element
Native input element patterns
Form Element
Native form element documentation