#32338: Accessibility issues with Django forms RadioSelect and
CheckboxSelectMultiple
-------------------------------------+-------------------------------------
Reporter: Thibaud | Owner: nobody
Colas |
Type: Bug | Status: new
Component: Forms | Version: master
Severity: Normal | Keywords: accessibility,
Triage Stage: | forms, wcag
Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 1 |
-------------------------------------+-------------------------------------
In the Forms API, there are issues with the default rendering of fields
that rely on widgets based on multiple radio or checkbox inputs:
`RadioSelect` and `CheckboxSelectMultiple`. This is with the default
rendering of those widgets. Here is a form I set up for my testing if it
helps:
- Live form: http://django-admin-tests.herokuapp.com/forms/example_form/p/
- Form fields definitions:
https://github.com/thibaudcolas/django_admin_tests/blob/main/django_admin_tests/forms.py
- Template:
https://github.com/thibaudcolas/django_admin_tests/blob/main/django_admin_tests/templates/django_admin_tests/example_form.html
== RadioSelect issues
1. The fields aren’t semantically grouped, only visually, so the grouping
isn’t apparent to assistive technlogies. It’s important that related
fields are grouped, and that the group has a label attached to it. If I
was auditing this professionally I would classify this as a fail for
[https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html
SC 1.3.1 - Info and Relationships] of WCAG 2.1, as the grouping and label
are somewhat there, just not done with the appropriate semantics.
2. Speaking of label – currently the group of fields is labeled by
preceding it with `<label for="id_radio_choice_required_0">Radio choice
required:</label>`. This overrides the label of the first field within the
group (and only labels the first field, not the whole group). This is a
fail for [https://www.w3.org/WAI/WCAG21/Understanding/labels-or-
instructions.html 3.3.2: Labels or Instructions] and/or SC 1.3.1.
3. Wrapping the fields each in their own list item makes the navigation
more tedious, as screen readers will first announce list items numbering,
and only then their content.
Here is a screenshot demonstrating the label issue with macOS VoiceOver’s
rotor. Note how the first field has the wrong label due to the markup.
radio-select-first-input-label.png
[[Image()]]
== CheckboxSelectMultiple issues
Almost identical to the above,
- Lack of a fieldset means no semantic grouping.
- The label isn’t associated with anything for this widget, so is less
problematic but no more correct.
- Wrapping the fields in list items also makes the form more verbose than
it should be (and the semantics issues are the same).
== Proposed solution
Essentially following [https://www.w3.org/TR/WCAG20-TECHS/H71 technique
H71] of WCAG. The ideal solution is identical for both:
1. Wrap the group of fields in a `fieldset`, including the group’s label,
the inputs, the help text, and any errors.
2. Use a `legend` as the first item in the `fieldset` for the group’s
label, rather than a `label`.
3. Replace the list markup with un-semantic div, or remove altogether. If
the list markup is needed for backwards compatibility, it could also use
`role="presentation"` so assistive technologies ignore the list & listitem
semantics, but I would only recommend that as a temporary workaround.
Here is sample markup to implement the above. The `div` aren’t needed,
I’ve only added them to preserve the vertical layout of the current
implementation:
{{{#!html
<fieldset>
<legend>Radio choice required:</legend>
<div><label for="id_radio_choice_required_0"><input type="radio"
name="radio_choice_required" value="one" required=""
id="id_radio_choice_required_0">
One</label></div>
<div><label for="id_radio_choice_required_1"><input type="radio"
name="radio_choice_required" value="two" required=""
id="id_radio_choice_required_1">
Two</label></div>
<div><label for="id_radio_choice_required_2"><input type="radio"
name="radio_choice_required" value="three" required=""
id="id_radio_choice_required_2">
Three</label></div>
<div><label for="id_radio_choice_required_3"><input type="radio"
name="radio_choice_required" value="four" required=""
id="id_radio_choice_required_3">
Four</label></div>
<span class="helptext">Help</span>
</fieldset>
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32338>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/055.59f430d0a2b3ff3849e3112bb8e1b066%40djangoproject.com.