Accessible Forms: Labels, Errors and Keyboard Paths
Tie labels to inputs, show errors next to the field, and keep the whole form usable with Tab and Enter. After this, people can finish the form without a mouse.
Course content
Sign in to save your progress.
-
Layout Without Float Hacks
-
Flexbox for Real Rows and Columns
-
CSS Grid When Flexbox Isn't Enough
-
-
-
Pages That Survive Phones
-
Responsive Layout With Media Queries That Make Sense
-
Mobile-First Without Building Everything Twice
-
Images and Typography That Scale Without Breaking
-
-
-
Components You Can Reuse
-
Navigation That Still Works on a Narrow Screen
-
Cards, Buttons and Shared Styles Across Pages
-
Custom Properties (CSS Variables) You Won't Regret
-
-
-
Forms and States That Look Finished
-
Focus, Hover and Disabled States People Can See
-
Accessible Forms: Labels, Errors and Keyboard Paths
-
-
-
Keep Layouts From Fighting You
-
Fix Overlap, Overflow and Z-Index Without Guessing
-
Organize CSS So You Can Find Things Later
-
-
- Final Check: HTML and CSS Intermediate
Skip ahead: If your forms already tie labels with for/id, show text errors next to fields, and work with Tab and Enter, skip to "Errors people can notice", then continue.
A form that looks pretty and fails a keyboard pass is not finished. Labels, errors and focus order are part of the layout job at this level.
Labels stuck to inputs
<form class="form" novalidate>
<div class="field">
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="email" required>
</div>
<div class="field">
<label for="note">Message</label>
<textarea id="note" name="note" rows="4" required></textarea>
</div>
<button type="submit" class="btn btn--primary">Send</button>
</form>
.field {
display: flex;
flex-direction: column;
gap: 0.35rem;
margin-bottom: 1rem;
}
.field input,
.field textarea {
font: inherit;
padding: 0.6rem 0.75rem;
border: 1px solid #626976;
border-radius: 6px;
}
.field input:focus-visible,
.field textarea:focus-visible {
outline: 3px solid #034bff;
outline-offset: 2px;
}
for on the label must match id on the control. Clicking the label focuses the field. Placeholders are not labels.
Errors people can notice
<div class="field field--error">
<label for="email">Email</label>
<input id="email" name="email" type="email" aria-invalid="true" aria-describedby="email-error">
<p id="email-error" class="field__error">Enter an email that includes @.</p>
</div>
.field--error input {
border-color: #d93025;
}
.field__error {
margin: 0;
color: #d93025;
font-size: 0.9rem;
}
Colour alone is not enough. The text states what to fix. aria-describedby ties the message to the input for assistive tech. aria-invalid="true" marks the state.
Keyboard path
- Tab moves through controls in DOM order. Do not shuffle with positive
tabindex. - Enter submits from a text field when a submit button exists.
- Escape is for dialogs you add later; keep the basic form simple.
⚠ Warning: Do not rely on alert() for every validation error. Inline field messages stay visible while the user edits.
Common mistakes
- Label text with no
for. Or wrapping quirks that break the association. - Errors only as a red border. Colour-blind users and screen magnifier users miss them.
- Custom widgets that ignore Enter. Prefer native controls until you must build otherwise.
Submit and the thank-you state
After a successful submit, tell the user what happened in the page — a confirmation message near the form, or a dedicated thank-you view. Do not rely on a silent clear of the fields. If you clear the form, the confirmation text must still be there.
<p class="form-success" role="status">Thanks. We got your message and will reply within one business day.</p>
role="status" helps assistive tech announce the update. Keep the message specific. "Success" alone is weak.
One more keyboard check
Tab from the address bar into the first field, through every control, to the submit button. Shift+Tab back. If focus jumps into the footer mid-form, your DOM order does not match the visual order — fix the HTML order or the layout, not with positive tabindex patches.
What happens if you skip this
Conversion drops. Support fills with "the button does nothing". Accessibility reviews fail on basics you could have fixed in an hour.
Try it
Build the form above. Submit empty. Show one clear error under Email. Tab through with the mouse unplugged.
If a user cannot tell which field failed, who is the form helping?
About
Tie labels to inputs, show errors next to the field, and keep the whole form usable with Tab and Enter. After this, people can finish the form without a mouse.
- Duration
- 5 min
- Last update
- 08/15/2026
Comments (0)
Sign in to commentNo comments yet.