How do you announce a validation error to a screen-reader user and tie it to the field?
Programmatic error association (aria-describedby/aria-invalid) and announcing errors, not just coloring them red.
A visible red border and message help sighted users but are invisible to screen readers unless wired up. Three pieces. (1) ASSOCIATE the error text with the field using aria-describedby pointing at the error element's id, so on focus the screen reader reads the label, then the value, then the error/hint. aria-describedby can list multiple ids (a format hint AND an error). (2) MARK the field invalid with aria-invalid="true" (and remove it when fixed) so the state is exposed programmatically, not just via colour. (3) ANNOUNCE on submit: move focus to the first invalid field (so the user lands on the problem and hears its error via describedby), or render an error SUMMARY at the top of the form inside a container that receives focus or is a live region, listing each error as a link to its field — the pattern GOV.UK popularised. Don't rely on the field turning red (fails use-of-color) and don't use placeholder for hints (vanishes). For inline/live validation, be careful: validating and announcing on every keystroke is noisy and can interrupt — validate on blur or submit, and if you use aria-live for a status, keep it polite. required/aria-required communicates the requirement up front. The recurring senior insight: the error must be perceivable (announced), programmatically related to its field (describedby), and reachable (focus moves to it) — not merely visible.
Wiring up form validation; making errors announced and reachable, not just red.
<label for="pw">Password</label>
<input id="pw" type="password"
aria-describedby="pw-hint pw-err"
aria-invalid="true" required>
<p id="pw-hint">At least 12 characters.</p>
<p id="pw-err">Password is too short.</p>
<!-- On submit, move focus to the first invalid field: -->
<script>document.getElementById('pw').focus();</script>
<!-- Or an error summary at the top, focused on submit, linking to each field -->
<div role="alert" tabindex="-1">
<h2>There is a problem</h2>
<ul><li><a href="#pw">Password is too short</a></li></ul>
</div>