﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
32819	Fields’ help text and errors should be associated with input	Thibaud Colas	David Smith	"With Django’s default field rendering, all field errors are rendered as a list above the field’s label, and help text is rendered after the field’s form element. Example with `as_p`:

{{{
<ul class=""errorlist"">
  <li>This field is required.</li>
</ul>
<p>
  <label for=""id_duration_required"">Duration required:</label>
  <input type=""text"" name=""duration_required"" required="""" id=""id_duration_required"">
  <span class=""helptext"">Help</span>
</p>
}}}

One problem for screen reader users is that the association between the errors and the field, and between the help text and the field, is only communicated visually. This is a failure of either WCAG 2.1 level A [https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html SC 1.3.1: Info and Relationships], or [https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions SC 3.3.2: Labels or Instructions]. More importantly, it just makes it harder than necessary for screen reader users to make use of help text, and to identify error messages.

The fix is relatively straightforward – using `aria-describedby`, as documented in the (non-normative) [https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA1.html ARIA1 Using the aria-describedby property to provide a descriptive label for user interface controls] technique. Here is another well-known accessibility-oriented UI library that implements this technique: [https://design-system.service.gov.uk/components/text-input/#error-messages GOV.UK design system – text input with error message].

Here is what implementing `aria-describedby` would look like in the same example as above:

{{{
<div class=""errorlist"" id=""id_duration_required_errorlist"">
  <p>This field is required.</p>
</div>
<p>
  <label for=""id_duration_required"">Duration required:</label>
  <input type=""text"" name=""duration_required"" required="""" id=""id_duration_required"" aria-describedby=""id_duration_required_errorlist id_duration_required_helptext"">
  <span class=""helptext"" id=""id_duration_required_helptext"">Help</span>
</p>
}}}

We have additional `id` attributes, `aria-describedby`, and `errorlist` is no longer a `<ul>`. Result in VoiceOver:

[[Image(https://code.djangoproject.com/raw-attachment/ticket/32819/email-required-ariadescribedby.gif)]]

Unfortunately I tried to have this with the `errorlist` kept as a `ul`, but it wasn’t announced by VoiceOver. I haven’t heard of this limitation before so am not sure why that might be the case – I’d appreciate others taking a look if possible.
"	Bug	closed	Forms	dev	Normal	fixed	accessibility, ui, forms		Ready for checkin	1	0	0	0	0	1
