Missing Required Field Indicators
Your form doesn't tell visitors which fields are mandatory. They submit, get errors, and rage-quit. Mark required fields properly.
What is this?
Imagine taking an exam where some questions are mandatory and some are optional — but nobody told you which is which. You skip a few, submit, and get a failing grade with a vague "incomplete" stamp. Infuriating, right? That is what your form feels like when required fields are not marked. Visitors fill out what they think is needed, hit submit, and get slapped with error messages for fields they did not even know were mandatory.
Why it matters
- For your visitors: Unmarked required fields create a guessing game. Sighted visitors might miss which fields are mandatory. Screen reader users have it even worse — without the
requiredattribute oraria-required, they have zero indication that a field must be filled in before they encounter a validation error. - For your business: Every time a form submission fails because of an unclear requirement, you risk losing a customer. Checkout abandonment, signup dropoff, and contact form frustration all increase when required fields are ambiguous.
- The standard: WCAG 3.3.2 (Labels or Instructions) requires that when content requires user input, labels or instructions are provided. This includes identifying which fields are required. The HTML
requiredattribute is the standard mechanism.
<form>
<label for="name">
Full name <span aria-hidden="true">*</span>
</label>
<input type="text" id="name" name="name" required />
<label for="email">
Email <span aria-hidden="true">*</span>
</label>
<input type="email" id="email" name="email" required />
<label for="company">Company (optional)</label>
<input type="text" id="company" name="company" />
</form><form>
<label for="name">Full name</label>
<input type="text" id="name" name="name" />
<label for="email">Email</label>
<input type="email" id="email" name="email" />
<label for="company">Company</label>
<input type="text" id="company" name="company" />
<!-- Which ones are required? Nobody knows until they fail -->
</form>How to fix it
React / Next.js
There are three layers to marking required fields: the HTML required attribute for browser validation, a visual indicator for sighted users, and an accessible indicator for screen readers.
// src/components/contact-form.tsx
export function ContactForm() {
return (
<form>
{/* Tell users upfront what the asterisk means */}
<p className="mb-4 text-sm text-neutral-500">
Fields marked with <span aria-hidden="true">*</span>
<span className="sr-only">asterisk</span> are required.
</p>
<div className="flex flex-col gap-1">
<label htmlFor="name" className="text-sm font-medium">
Full name{" "}
<span className="text-red-500" aria-hidden="true">
*
</span>
</label>
<input
type="text"
id="name"
name="name"
required
aria-required="true"
className="rounded border px-3 py-2"
/>
</div>
<div className="flex flex-col gap-1">
<label htmlFor="email" className="text-sm font-medium">
Email address{" "}
<span className="text-red-500" aria-hidden="true">
*
</span>
</label>
<input
type="email"
id="email"
name="email"
required
aria-required="true"
className="rounded border px-3 py-2"
/>
</div>
<div className="flex flex-col gap-1">
<label htmlFor="message" className="text-sm font-medium">
Message{" "}
<span className="text-red-500" aria-hidden="true">
*
</span>
</label>
<textarea
id="message"
name="message"
required
aria-required="true"
rows={4}
className="rounded border px-3 py-2"
/>
</div>
<div className="flex flex-col gap-1">
{/* Optional field: no asterisk, no required attribute */}
<label htmlFor="phone" className="text-sm font-medium">
Phone number <span className="text-neutral-400">(optional)</span>
</label>
<input type="tel" id="phone" name="phone" className="rounded border px-3 py-2" />
</div>
<button type="submit" className="mt-4 rounded bg-blue-600 px-6 py-2 text-white">
Send message
</button>
</form>
);
}For a reusable field component:
// src/components/form-field.tsx
interface FormFieldProps {
label: string;
name: string;
type?: string;
required?: boolean;
}
export function FormField({ label, name, type = "text", required = false }: FormFieldProps) {
return (
<div className="flex flex-col gap-1">
<label htmlFor={name} className="text-sm font-medium">
{label}
{required && (
<span className="text-red-500" aria-hidden="true">
{" "}
*
</span>
)}
{!required && <span className="text-neutral-400"> (optional)</span>}
</label>
<input
type={type}
id={name}
name={name}
required={required}
aria-required={required}
className="rounded border px-3 py-2"
/>
</div>
);
}Plain HTML
<form>
<!-- Explain the convention at the top -->
<p>Required fields are marked with an asterisk (*).</p>
<!-- Required field: required attribute + visual asterisk -->
<div>
<label for="email"> Email address <abbr title="required" aria-label="required">*</abbr> </label>
<input type="email" id="email" name="email" required aria-required="true" />
</div>
<!-- Optional field: explicitly label it optional -->
<div>
<label for="website">Website (optional)</label>
<input type="url" id="website" name="website" />
</div>
</form>
<!-- Or flip it: if MOST fields are required, label the optional ones instead -->
<form>
<div>
<label for="name">Full name</label>
<input type="text" id="name" name="name" required aria-required="true" />
</div>
<div>
<label for="nickname">Nickname <span class="optional">(optional)</span></label>
<input type="text" id="nickname" name="nickname" />
</div>
</form>Best practices:
- Always add the HTML
requiredattribute — it enables built-in browser validation - Add
aria-required="true"as a belt-and-suspenders approach for older screen readers - Use a visual indicator (asterisk or "required" text) for sighted users
- If most fields are required, label the optional ones instead — less visual clutter
- Explain the asterisk convention at the top of the form
Forms are where your visitors become customers. Every unmarked required field is a potential drop-off point. The cat expects clear labels and will flag every ambiguous form.
How the cat scores this
The cat inspects every form on your page and checks each input for the required attribute or aria-required="true". It also looks for visual indicators — asterisks, "required" text, or "(optional)" labels on non-required fields. Forms where required fields have no required attribute get flagged as errors. Forms with required attributes but no visual distinction between required and optional fields get flagged as warnings — because sighted users need to know too.
Further reading
- WebAIM: Required Form Fields — best practices for marking required fields
- WCAG 3.3.2: Labels or Instructions — the standard
- MDN: The required attribute — reference for HTML form validation