Web Forms

2019-03-07

This page will probably always be a work in progress. It's not the only way to do things, but I mean for it to be a useful reference for myself on what I've learned. I hope it might be useful for others as well.

There are a lot of common issues with web form design that can make a form inaccessible or exclusionary. Some things to consider include:

It's important that disabled users are able to fill in your web forms. This means they have to be usable with screen readers, and navigable via the keyboard.

By default, form elements such as input, select, and textarea can receive focus via the keyboard.

Wrapping inputs in an ol will allow screen readers to report the number of items in the list when a user enters the list.

Labelling inputs

The same information should be presented to users that use screen readers and to users relying on visual cues. The simplest way to do this is to associate a label tag with every input.

A label can be linked to an input either by having a for attribute with the input's id as its value, or by being a parent of the input. This example uses a for attribute:

Labels linked to inputs in this way also have the advantage of moving focus to the linked input when the label is clicked. This means it can sometimes be useful to associate multiple label elements with a single input.

To be explicit about which label should be read out when the input receives focus, the input can be given an aria-labelledby attribute with the label element's id as its value:

A placeholder attribute can also be used by screen readers to read out the label of an input, but once the input has a value entered in it this prompt will no longer be visible.

Some designs implement a label that appears when the placeholder is hidden. Testing with NVDA, if an input only has a placeholder attribute, and no visible label, then its placeholder text will be treated like a label.

However, if there is both a placeholder attribute and a label, then both will be read out if the placeholder is visible, but only the label will be read out if the input has a value. This means approaches that cause only one of either the placeholder or the label to be visible at any given time should not result in the same text being read out twice, and the input will always have label text.

Cautionary note This example uses :placeholder-shown to avoid the need for custom JavaScript for a one-off example. At the time of writing, this pseudoclass has poor browser support, so should not be relied on.

Autocomplete

See the autocomplete component page for an example of an accessible autocomplete input.

Styling radio buttons and checkboxes

Because some common form elements cannot be styled heavily in CSS, it is common for other elements (which can be styled) to be used as proxies for them. When this is done, it should be done accessibly.

These fake radio buttons and checkboxes rely on the presence of an input element that is not visible, but is still read out by screen readers and can receive focus via the Tab key.

To achieve this, the following CSS rules are used on the input:

position: absolute;
display: block;
width: 1px;
height: 1px;
opacity: 0;
pointer-events: none;

The visible element in this example is a span tag (though various other tags could be used instead), which can be styled much more freely. It uses the adjacent sibling selector to change its appearance based on the state of the semi-hidden input element, using the :focus and :checked pseudoclasses. For example:

.fake-input__input[type="radio"]:checked + .fake-input__display::before {
	content: "✓"
}

Though the input element itself has pointer-events: none; on it, the whole group is wrapped in a label tag. This causes the click to be delegated to the input element, so it still behaves like a normal radio button or checkbox in this respect.

Styled radio buttons

Styled checkboxes

Modern browsers support native form validation that allows the browser to handle validation rules and reporting errors to the user. However, these error messages are not always reported to users who use screen readers.

The validation JavaScript running on this page relies on the browser to determine which inputs are valid and invalid.

Because browser application of the :invalid pseudoclass on initial load is inconsistent, the JavaScript applies an is-validated class to the form when it fails validation. Styles association with invalid inputs depend on the presence of this class, so fields will not appear invalid by default.

When a form fails to submit, this JavaScript displays a message at the end explaining that the form failed to submit due to a specific number of invalid inputs. This message is read out due to the presence of aria-live="polite".

The actual validation rules, as well as helping the user correct the errors that prevented the form from being validated, are left up to the browser.

Required field

The presence of a required attribute is specified by screen readers. Other validation requirements are not. These include:

  • "email" or "url" inputs.
  • The pattern attribute, which specifies a regular expression against which a field should be validated.
  • The minlength attribute (modern browsers prevent adding text beyond a specified maxlength).
  • "number" inputs that have min, max, or step attributes.

It's common for web forms to be designed in a way that is unnecessarily exclusionary. This may be because it's been made impossible for someone to fill out a form without lying, or because the form requires them to provide personal information that shouldn't be necessary for the purpose of the form.

For example, if a form requires users to fill in a "gender" field but only offers "male" and "female" as options, it is excluding nonbinary people. They can't fill in the form without lying.

Requiring users to provide unnecessary information can be more generally exclusionary. For example, I have seen a web form for unsubscribing from an email mailing list that could not be submitted unless a postal address was provided.

As I've thought about this, I've come up with what I consider some fundamental principles of inclusive web form design:

  • Ask for the information you need.
  • Don't make anyone lie to you.

If you need information for a single purpose, being explicit about that purpose when you ask for it can help the user filling out the form understand how their information will be used.

Here is an example:

How should we address you?

How to address someone

A common purpose of fields in a web form is knowing how to address someone. Often this means using their name to greet them when sending them an email, and it can also be useful to know which pronoun to use when referring to them in the third person.

Please call me ______

"What is your name?" might be a clearer question in many contexts, but I think "How should we address you?" has the advantage of making it clear how this information is intended to be used.

Web forms often split name into separate required fields. This almost always includes a first name, and often also includes a last name and a title.

Though it's uncommon in most cultures, not everyone has two names. If you require a person with one name to enter two names in order to submit your form, you are requiring them to lie.

Also, referring to name parts as "first name" and "last name" centres cultures that present full names in this way, whereas other cultures present full names with a family name first and a personal name last. Names are complicated.

Requiring users to pick a title from a finite list can require them to provide more information than necessary. For example, forcing women filling in your form to choose between "Miss" or "Mrs", in cases where other titles such as "Dr" do not apply to them, is effectively asking them to disclose their marital status.

Requiring users to choose a title can also require them to lie, if you have not provided any titles that would apply to them. Often, the only gender-neutral titles available in such a list are tied to qualifications, such as "Dr". This can leave nonbinary people without those qualifications with no option available that they can honestly say applies to them, but the form may not let them submit anything unless they choose one.

Often, the only purpose a user's name and title is used for is in addressing the user in correspondence. Asking users a question that refers directly to the purpose for which the information is intended to be used gives them the opportunity to provide the required information in a way that works for them.

This way, users that prefer to be addressed informally may simply provide a personal name, or a nickname. Those that prefer to be addressed more formally may provide a title and surname.

My gender is ______

Many web forms that ask for a user's gender don't need to ask for this question. If you don't need to know, you don't need to ask.

If your reason for asking is that you need to know what pronouns to use to refer to a user, then consider asking them for that information instead.

As with requiring users to specify a title, requiring users to pick from a finite list of genders often means nonbinary people cannot fill in your form without lying.

A common explanation for providing a finite list of genders instead of having a free-text field is that it could be difficult to interpret the various responses. However, there is evidence that this approach does not lead to such problems:
Coding Responses to an Open-ended Gender Measure in a New Zealand National Sample

If you do need to know a user's gender, make sure your form allows them to tell you what their gender is. If you're worried about inconsistent entries, try to find a solution that doesn't make it difficult for anyone to fill in your form honestly.

What can I do to improve this page?

These are topics I care about, but I am not an expert in them. A lot of the issues that can cause web forms to be inaccessible or exclusionary do not apply to me directly, so I'm sure I will be ignorant of some issues.

If you think there's something I can do to improve this page, please let me know!