HTML Forms
Modern, accessible, autofill-ready form patterns using the full web platform — no library dependencies.
I need to...
| I need to... | Guide | Summary |
|---|---|---|
| Structure a form with correct semantics, labels, and grouping | Form Structure & Semantics | Wrap all controls in form, use fieldset+legend for groups, always associate label for with input id. Never disable the submit button for validation — keyboard users cannot trigger invalid events. |
| Pick the right type, inputmode, and enterkeyhint for mobile keyboards | Input Types & Modes | Use type="text" + inputmode="numeric" for card numbers and ZIP codes — never type="number" which strips leading zeros. Set enterkeyhint on every field in multi-step forms. |
| Wire autocomplete tokens for address, payment, sign-in, sign-up | Autocomplete & Autofill | Add autocomplete to every input, select, and textarea. Use autocomplete="username" on sign-in email inputs. Never use autocomplete="off" on password fields. |
| Style fields that the browser has autofilled | Autofill Visual Feedback | Use box-shadow inset to simulate background-color — background-color is blocked by the browser's security model. Always include :autofill:focus-visible with an explicit outline. |
| Show validation errors only after user interaction | Native Validation | Use :user-invalid (not :invalid) so errors appear only after the user interacts. Bridge to AT with aria-invalid="true" via JS on blur and submit — :user-invalid is CSS-only and invisible to screen readers. |
| Make inputs and textareas auto-grow to fit content | Field Sizing | Use field-sizing:content as progressive enhancement — Chrome/Edge 123+, Safari 26.2+, not Firefox. Set min-inline-size on inputs; fixed width on textareas. Feature-detect with @supports. |
| Style a select on-brand without building a JS widget | Styling Native Select | appearance:base-select is Chrome/Edge 135+ only; degrades gracefully. Apply to both the element AND ::picker(select). Grid layouts do not give 2D keyboard navigation. |
| Embed icons or descriptions inside option elements | Rich Media Input | Use appearance:base-select + HTML in option. Older browsers render text nodes only — always include meaningful plain text. Add aria-label to options with complex rich content. |