Forms
Text inputs, select, textarea, checkboxes, radios, validation states, and helper text.
ASW styles all standard form elements via element selectors — no wrapper classes needed. Labels are block-level by default. Fields expand to full container width. Validation state is communicated through aria-invalid, keeping semantic meaning intact and observable by assistive technology.
Text input
A <label> wrapping an <input> is the simplest form pattern. The label is correctly associated by containment — no for/id pair needed, though both approaches work.
<label>Email address
<input type="email" name="email" placeholder="you@example.com">
</label>
Live demo
Inputs are 100% wide by default. To constrain width, wrap the label in a container with a width or grid column.
Textarea
A multi-line input. ASW sets resize: vertical so users can adjust height but not accidentally break horizontal layout.
<label>Message
<textarea name="message" rows="4" placeholder="Your message…"></textarea>
</label>
Live demo
Select
A dropdown select. The chevron indicator is a CSS background image injected by --asw-icon-chevron — no icon font or SVG needed. Multi-select ([multiple]) drops the chevron and applies accent colour to selected options.
<label>Country
<select name="country">
<option value="">Select…</option>
<option value="de">Germany</option>
<option value="fr">France</option>
<option value="it">Italy</option>
</select>
</label>
Live demo
Hold Ctrl (Windows/Linux) or ⌘ (macOS) to select multiple options.Checkboxes and radios
ASW uses accent-color to theme native checkboxes and radio buttons to the framework's accent colour. They remain native controls — no custom SVG replacements.
There are two placement patterns: inline label wrapping, and sibling label. Both work correctly with ASW.
Wrapping label (recommended)
<label>
<input type="checkbox" name="agree">
I agree to the terms
</label>
Live demo — checkboxes
Live demo — radios
Sibling pattern
Alternatively, place the checkbox/radio before the label as a sibling. The for/id association is required in this pattern.
<input type="checkbox" id="agree" name="agree">
<label for="agree">I agree to the terms</label>
Fieldset and legend
<fieldset> groups related fields under a <legend> header. ASW strips the fieldset border and resets padding — the visual grouping comes from layout and the legend label, not a box.
<fieldset>
<legend>Billing address</legend>
<label>Street <input type="text" name="street"></label>
<label>City <input type="text" name="city"></label>
<label>Postcode <input type="text" name="postcode"></label>
</fieldset>
Live demo
Helper text
Place a <small> element immediately after an <input>, <select>, <textarea>, or <fieldset> to render muted descriptive text. The margin is negative to close the gap left by the field's bottom margin.
<label>Username
<input type="text" name="username">
</label>
<small>3–20 characters, letters and numbers only.</small>
Live demo
3–20 characters, letters and numbers only. Read-only. Contact your administrator to rotate this key.Validation states
Set aria-invalid="true" on an invalid field and aria-invalid="false" on a valid one. ASW applies red border for invalid and accent border for valid. Helper text inherits the corresponding colour automatically.
<!-- Invalid -->
<label>Email
<input type="email" aria-invalid="true" value="not-an-email">
</label>
<small>Enter a valid email address.</small>
<!-- Valid -->
<label>Username
<input type="text" aria-invalid="false" value="vigilio">
</label>
<small>Username is available.</small>
Live demo
Enter a valid email address. Username is available. Message must be at least 20 characters.Use aria-describedby to associate the helper text element with the input when they are not adjacent siblings, or when you need to be explicit for assistive technology.
Disabled fields
Apply disabled to prevent interaction. Opacity drops to --asw-disabled-opacity. Disabled fields are excluded from form submission.
<label>Account type
<input type="text" disabled value="Free tier">
</label>
Live demo
Upgrade to change this.Complete form example
A full login form demonstrating the patterns above in combination.
<form method="post" action="/login">
<fieldset>
<legend>Sign in</legend>
<label>Email
<input type="email" name="email" autocomplete="email" required>
</label>
<label>Password
<input type="password" name="password" autocomplete="current-password" required>
</label>
<label>
<input type="checkbox" name="remember">
Remember me
</label>
</fieldset>
<button type="submit">Sign in</button>
<a href="/forgot-password">Forgot password?</a>
</form>
Live demo
Design tokens
| Token | Controls |
|---|---|
--asw-input-bg |
Field background colour (default: secondary bg) |
--asw-input-border |
Field border colour (resting state) |
--asw-input-active-bg |
Field background on focus/active |
--asw-input-padding-y |
Vertical padding inside fields |
--asw-input-padding-x |
Horizontal padding inside fields |
--asw-input-selected |
Selected option background in multi-select |
--asw-error |
Border colour for aria-invalid="true" |
--asw-disabled-opacity |
Opacity for disabled form controls |
Accessibility
- Every input must have an associated label. Use the wrapping pattern (
<label><input></label>) or thefor/idpair. Placeholder text is not a label. aria-invalidis the correct mechanism for communicating validation state to assistive technology. Don't rely on border colour alone.- Group related radio buttons and checkboxes in a
<fieldset>with a<legend>. Screen readers announce the legend before each control in the group. - Use
autocompleteattributes on login and payment forms. It aids users with memory or motor impairments and is required for WCAG 1.3.5 (AA). - Required fields: use the
requiredattribute — it prevents native form submission without a value and exposes the requirement to assistive technology. Don't rely solely on a visual asterisk.