How to Make Your Forms Accessible: Complete Guide
Picture this: someone's using a screen reader to fill out your signup form. Six fields, no labels. The screen reader just keeps saying "edit text, blank" over and over. They have no idea if they're typing their name or their credit card number.
This happens constantly. Forms are where accessibility fails hardest. And the fixes are embarrassingly simple.
Labels. Please. I'm Begging You.
Every input needs a label. Not a placeholder. A label.
<!-- screen reader says: "edit text" ...helpful -->
<input type="email" placeholder="Email">
<!-- screen reader says: "Email, edit text" -->
<label for="email">Email</label>
<input type="email" id="email">The for attribute connects to the input's id. That's what makes it work. Without that connection, it's just text sitting near a box.
You can also wrap inputs in labels and skip the for/id thing:
<label>
Email
<input type="email">
</label>Both are fine. Just do one of them. Please.
"But I have a placeholder!" Placeholders disappear when you start typing. They're hints, not labels. Also, most placeholder text has terrible contrast. Stop using them as labels.
Input Types: Free Accessibility
Here's something that takes zero extra effort:
<input type="email">
<input type="tel">
<input type="date">Using the right type gets you the right keyboard on phones, built-in validation, and better screen reader announcements. Free. No extra work. Just type the correct word.
While you're at it, add autocomplete:
<input type="text" autocomplete="name">
<input type="email" autocomplete="email">
<input type="text" autocomplete="street-address">Autofill is a big deal for people with motor impairments. Typing hurts. Let the browser fill stuff in.
Required Fields: The Asterisk Isn't Enough
You know the little red asterisk that means "required"? Screen readers don't see color. And if you don't explain what the asterisk means, it's just a weird star.
<label for="name">
Name *
<span class="sr-only">(required)</span>
</label>
<input type="text" id="name" required>The .sr-only class hides text visually but keeps it available to screen readers. And the required attribute on the input handles validation.
Oh, and put "fields marked with * are required" somewhere on the form. Preferably at the top. Plenty of forms never explain what the asterisk means. Just floating there. Mysterious.
Error Messages
"Invalid input."
Invalid HOW? WHERE? Users have typed into six fields, they need to know which one is wrong.
Be specific:
<span class="error">Password must be at least 8 characters</span>And connect errors to fields so screen readers announce them:
<input type="email" id="email" aria-invalid="true" aria-describedby="email-error">
<span id="email-error">Please enter a valid email address</span>When someone tabs to that field, they'll hear the error. Without aria-describedby, they might never find it.
For long forms, put all errors in a summary at the top when submission fails. With links to jump to each problem field. Nobody should have to scroll around hunting for red text.
Fieldsets Exist For A Reason
Got a mailing address with street, city, state, zip? Wrap it in a fieldset:
<fieldset>
<legend>Mailing Address</legend>
<!-- fields go here -->
</fieldset>The legend announces the group. So screen readers say "Mailing Address, Street, edit text" instead of just "Street, edit text" with no context.
Radio buttons especially need this. Without a fieldset, users hear "Email, radio button" but never hear the question. What's email? Email for what?
<fieldset>
<legend>Preferred contact method</legend>
<input type="radio" id="c1" name="contact" value="email">
<label for="c1">Email</label>
<input type="radio" id="c2" name="contact" value="phone">
<label for="c2">Phone</label>
</fieldset>Now they hear the question before the options. Makes sense. Works correctly.
Testing
Tab through your form start to finish. Can you reach everything? Do you know what each field is for? Can you submit it?
Then try submitting with errors. Do you know what went wrong? Can you find the problem fields?
If you want to really understand the experience, turn on VoiceOver (Mac) or NVDA (Windows) and try to complete the form eyes-closed. Humbling experience. Highly recommend.
Or just scan it with ClearA11y and get a report of what's broken. Either way. Just test it somehow before shipping.
Check Your Site's Accessibility
Find and fix accessibility issues with AI-powered code suggestions.
Start Free ScanStay Updated on Web Accessibility
Get practical accessibility tips, WCAG updates, and guides delivered to your inbox. No spam, unsubscribe anytime.
We respect your privacy. Unsubscribe at any time.