Required and optional, signaled accessibly
Three audiences need to know a field is required: sighted users, screen reader users, and the browser itself. One signal isn't enough.
Forms always have a mix of required and optional fields. The trouble is, "required" needs to reach three audiences at once: sighted users skimming the form, screen reader users listening field-by-field, and the browser doing built-in validation. If you only do one of those, the other two are flying blind.
This lesson is about wiring all three signals at once — and the small judgment call about whether to mark the required fields or the optional ones.
The required attribute
The required attribute is the HTML one-liner. Add it to an input, and:
- The browser blocks form submission until the field has a value.
- Most assistive tech announces "required" alongside the field's name.
- The
:requiredCSS pseudo-class is available for styling.
<label for="email">Email</label> <input id="email" name="email" type="email" required />
That's it. One word and you've covered all three audiences — almost. The asterisk for sighted users is still your job; we'll get there.
required is a boolean attribute. Just required is enough; you don't need required="true".
aria-required and when you'd reach for it
aria-required="true" does the same announcement job as required for screen readers — but doesn't block submission and doesn't give you :required for free. So when would you use it?
- Custom widgets where there's no real
<input>— like a comboBox built from<div>s and ARIA. - Forms where you handle validation yourself in JS and don't want the browser's native error bubble.
For everything else, prefer required. Only fall back to aria-required when the native one isn't available or you've taken the validation reins entirely.
<!-- A custom date picker built from divs needs aria-required --> <div role="combobox" aria-required="true" aria-label="Birth date"> … </div>
The asterisk convention
Sighted users learned to read * as "required" two decades ago. It's the cheapest visual signal you can ship. The trick: don't make the asterisk part of the label text (that puts a literal star in the accessible name). Use a separate element and either hide it from screen readers or pair it with a legend that explains what the star means.
<label for="email"> Email <span aria-hidden="true" class="req-mark">*</span> </label> <input id="email" name="email" type="email" required />
aria-hidden="true" keeps the visible asterisk for sighted users while telling assistive tech "don't read this character." The required attribute already announces "required" — the asterisk would just duplicate that.
Then somewhere visible at the top of the form:
<p><span class="req-mark" aria-hidden="true">*</span> indicates a required field.</p>
Don't put the asterisk inside the label text without aria-hidden. Some screen readers will read it as "star Email," which is exactly the kind of noise you're trying to avoid.
Marking optional, not required
If most fields on your form are required, flip the convention: mark the optional ones instead. Less visual clutter, less repetition.
<label for="middle-name"> Middle name <span class="opt-mark">(optional)</span> </label> <input id="middle-name" name="middle-name" />
Here you don't need aria-hidden because "(optional)" is real, useful text — let the screen reader read it. The user hears "Middle name optional, edit." Clear.
What you should not do is write "Middle name (optional)" on some fields and *"Email " on others on the same form. Pick one convention per form. Mixed signals make users guess.
Form-level instructions
Anything that applies to the whole form — "All fields required unless marked optional", "Phone is used only for delivery updates" — belongs in a single block at the top, before the first field. Sighted users see it as they enter the form. Screen reader users meet it the moment they reach the form's heading.
The biggest mistake is hiding instructions inside placeholder text or in tooltips that only appear on hover. Tooltips don't work on touch screens, placeholders disappear on type, and neither survives a screen reader's field-by-field navigation.
If an instruction applies to one field, attach it with aria-describedby on that field. If it applies to the whole form, write it once at the top as plain text.